首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 中国人发明的一种独特有趣的新排序法 — 张仰彪第二排序法
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 18:34:35 楼主
                                              引 子               

        去年,我曾经在CSDN的论坛里发表了我写的第一种排序法:“张仰彪排序法”,没想到就像捅了马蜂窝,在论坛里引起一场渲染大波,赞同的几乎没有,扔板砖的倒是不少,至今够盖一座楼的了。各色人等纷纷粉墨登场,说啥的都有,归纳起来就是一句话:“不许革命!”
        平心而论,倒也不能把这些唱反调的人统统与赵举人之流划为一类,因为他们说的也有一定道理,用两个数组排序确实是一个缺点,尽管瑕不掩瑜,但人家就是揪住这一点不放,唯一让他们改变观点的办法就是拿出更好的东西来。
        皇天不负有心人,经过近一年的潜心研究,我还真的写出了一种新的排序法,这次是用一个数组排序,其原理和算法过程非常独特有趣,而且我在网上搜索到了很多排序算法,与我的新排序算法都截然不同,甚至不用仔细看代码,搭眼一看它们的运行例图就可以知道它们之间差距很大。因为我的新排序法在排序时几乎始终守着数据队列的头部,就像我们中国的舞龙,始终抓着龙头就把整条龙排好了,仅这一点就与其他任何一种排序法不同。
        我原来写的那个“张仰彪排序法”确实有点逗乐的成分在里边,一方面活跃一下气氛、和大家认识一下,另一方面可以起到抛砖引玉的作用,为我现在写的这款新的排序法做个铺垫。
        至于此新的排序法究竟如何,请看下文,各位看官您见仁见义,欢迎发表高见,无论鲜花还是板砖,在下随时恭候,统统笑纳。而且保证物尽其用:鲜花送美,板砖盖房。

    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 18:40:381楼 得分:0
    讲故事啊...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 18:46:032楼 得分:0

                            张仰彪第二排序法 

        张仰彪第二排序法的原理与目前非常流行的反恐类网络游戏有些类似,它将待排序数组内放错位置的数据视为隐藏在节日游行队列里故意站错位置的恐怖分子,并自动地将这些恐怖分子按照它们相互之间的内在关系而分成几个不同的小组。排序时反恐队员首先从游行队列的最前头开始清查,若遇到的人是好人,就快速通过去查下一个。如果查到一个站错位置的恐怖分子,就停下来在这个位置上连续地排查运作,直到将这个恐怖分子及其所在小组的全部成员都清理到正确的位置上,然后才继续前行去查下一个位置。直到清查的次数比队列的长度小1时,尽管此时反恐队员可能仅沿着游行队列前行了很短的一段距离,还处在队列的头部,但队列中所有站错位置的恐怖分子都已被清理到了正确的位置上,排序完毕。
       
        下面给出张仰彪第二排序法的C语言代码:
    ------------------------------------------------------------------------------------------
    # include < stdio.h >
    void  main ( )
    {
      int  a [10];
      int  i;              /* 记录排序的次数,并用于输入输出 */
      int  j = 0;            /* 记录当前排序的位置 */
      int  temp;          /* 数据交换时的存储中介 */
      int  order;          /* 记录数据在数组里的大小排名,从小向大算 */

      printf ( " Input 10 numbers:\n" );
      for ( i=0;i < 10;i++ )          /* 输入任意10个整数 */
          scanf ( " %d",&a[i] );
      printf ( " \n" );

      for ( i=0;i < 9;i ++ )        /* 排序的总次数比待排序数组的长度小1 */
      {
          order = j;              /* 数据的排名从当前位置开始向后计算 */
          for ( int x = j+1;x < 10;x ++ )      /* 计算当前数据在数组里的排名 */
            if ( a[x] < a[j] )  order ++;             
         
          if ( order > j )      /* 如果当前数据的排名大于它现在的位置 */ 
          {
            while ( a[j] = = a[order] )  order ++;  /* 处理数组里的重复数据 */
            temp = a[order];          /* 将这个数据交换到正确的位置上 */
            a[order] = a[j];
            a[j] = temp;
          }
          else        /* 如果当前数据的排名等于(不可能小于)它现在的位置 */ 
            j ++;                    /* 开始排下一个位置上的数据 */     
      }

      printf ( " The sorted numbers is:\n" );
      for ( i=0;i < 10;i ++ )          /* 输出排好序的10个整数 */
          printf ( " %d",a[i] );
      printf ( " \n" );
    }
    -------------------------------------------------------------------------------
        下面是本排序法的算法例子,其中带下划线的数是已排好位置的数,红色的数是当前排序的位置。

    4, 5, 2, 4, 1, 3,0,2, 2,0 }
    第1步: 排位置0上的数"4", 有7个比它小得数, 它的排名为7,
            由于排名7大于位置0,
            所以将它与位置7上的数"2"交换。
            数组现在变为:

    2, 5, 2, 4, 1, 3,0,4, 2,0 }
    第2步: 排位置0上的数"2", 有3个比它小得数, 它的排名为3,
            由于排名3大于位置0,
            所以将它与位置3上的数"4"交换。
            数组现在变为:

    4, 5, 2, 2, 1, 3,0,4, 2,0 }
    第3步: 排位置0上的数"4", 有7个比它小得数, 它的排名为7,
            由于排名7大于位置0,
            所以将它与位置7上的数"4"交换。
            由于将要交换的两个数相等,
            所以延后一个位置,将它与位置8上的数"2"交换,
            数组现在变为:

    2, 5, 2, 2, 1, 3,0,44,0 }
    第4步: 排位置0上的数"2", 有3个比它小得数, 它的排名为3,
            由于排名3大于位置0,
            所以将它与位置3上的数"2"交换。
            由于将要交换的两个数相等,
            所以延后一个位置,将它与位置4上的数"1"交换
            数组现在变为:

    1, 5, 2, 22, 3,0,44,0 }
    第5步: 排位置0上的数"1", 有2个比它小得数, 它的排名为2,
            由于排名2大于位置0,
            所以将它与位置2上的数"2"交换。
            数组现在变为:

    2, 5, 122, 3,0,44,0 }
    第6步: 排位置0上的数"2", 有3个比它小得数, 它的排名为3,
            由于排名3大于位置0,
            所以将它与位置3上的数"2"交换。
            由于将要交换的两个数相等,
            所以延后一个位置,将它与位置4上的数"2"交换
            由于将要交换的两个数相等,
            所以延后一个位置,将它与位置5上的数"3"交换
            数组现在变为:

    3, 5, 1222,0,44,0 }
    第7步: 排位置0上的数"3", 有6个比它小得数, 它的排名为6,
            由于排名6大于位置0,
            所以将它与位置6上的数"0"交换。
            数组现在变为:

    0, 5, 1222344,0 }
    第8步: 排位置0上的数"0", 有0个比它小得数, 它的排名为0,
            由于排名0不大于位置0,
            所以不进行交换,开始排下一个位置上的数。
            数组现在变为:

    051222344,0 }
    第9步: 排位置1上的数"5", 有9个比它小得数, 它的排名为9,
            由于排名9大于位置1,
            所以将它与位置9上的数"0"交换。
            数组现在变为:

    0, 0, 12223445 }

    第10步:已进行了9次排序,排序的次数正好比数组的长度小1,排序结束。
    -------------------------------------------------------------------------------------
        可以看出,此排序法的空间效率和时间效率都与冒泡排序法相当,而且此排序法也具有一定的智能。对于排列非常混乱的数组,此排序法要进行很多数据比较和数据交换,比较费时。但当待排序数组基本有序时,此排序法只进行数据比较,而数据交换操作则很少,时间效率将大幅提高。
        同时,此排序法的原理非常独特有趣,并且富含中国古老文化的精髓和神韵。在排序时它几乎很少沿着待排序数组的数据队列前行,而是守着数据队列的头部,犹如姜太公稳坐钓鱼台,将队列里站错位置的乱臣贼子逐个擒过来、推出去,吐故纳新、收放自如,象极太极推手,又象中国的舞龙,不经意间,一列混乱的数据已成清一色一条龙。而且此排序法在运作时,可以将数组里所有放错位置的数据自动分组,一次清理完一组才继续前行,又恰似西游记里的三藏师徒,刚踏上西行路就遇到老妖怪,于是师徒几人便停下来降妖捉魔,直到将这老妖怪及其洞中所有的小妖全部剿灭,才继续西行,而没走几步,又遇到一股妖魔鬼怪,于是又停下来与妖怪大战一番......
        可见,在排序原理上张仰彪第二排序法极为独特,与现有的任何一种排序法都不相似,它应当是一种全新而有效的排序法,信不信由你。
        至于为什么此排序法具有将数组里放错位置的数据自动分组、按组排序的功能,老纳作了如下分析:
        首先,在任何一个待排序数组里,所有放错位置的数据都可以按照它们之间的内在关系而被分成很多小组,小组有大有小,但任何一个小组都不能再被分成更小的组。
        例如:有100个人按年龄(有同龄的)顺序坐成一排照相,若其中只有两个人发现自己坐错了位置,这两个人必然相互坐到了对方的位子上,只要两人对调即可,与别人无关。如果只有三个人甲、乙、丙发现自己坐错了位子,那么这三个人必然是相互轮错,例如甲坐到了乙的位子上,乙坐到了丙的位子上,丙坐到了甲的位子上,此三个人构成了一个错位三角,也可以说构成了一个错位环。如果有四个以上的人发现自己坐错了位置,情况就变得比较复杂,此时所有坐错位置的人将被分成一个个小组,每个小组里的人都是相互间轮流坐错了位子,与组外的人无关,整个小组构成一个封闭的错位环,此环不可再分,这个错位环就是前边所说的某些错位数据之间的内在关系,也是将数组内所有错位数据分组处理的唯一依据。
        既然待排序数组内的错位数据具有可以分组的特点,那么本排序法在排序时每遇到一个错位数据其实就是遇到了一组错位数据。所以将一个数据放到正确的位置上后交换过来的一定仍是一个错位数据,于是再将它放到正确的位置上,而交换过来的可能又是一个错位数据,只有将这一组错位数据全部清理到正确的位置上,排序位置才继续前移,直到又遇到另一组错位数据 ......。而此过程中无论怎样交换数据都不会移动原本就在正确位置上的数据,也不会移动刚刚排好位置的数据,这一点至关重要。
        而整个排序过程中排序位置究竟可以从数组头部前移多远,取决于待排序数组里原来有几个没有错位的数据。
    ----------------------------------------------------------------------------------------   
        这就是张仰彪第二排序法,爱咋咋地。
        编自己的程,下自己的蛋,让别人说去吧。

                                  < 完 >


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 18:59:153楼 得分:0
    虽然没怎么听懂,但还是佩服!

    不过楼主能不能写成C#语言,我看不太懂C
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 19:15:064楼 得分:0
    现在很少有人在搞发明了,这确实很难.
    尤其是在排序法这个领域,似乎是个雷区,
    有些人自己写不出新的很好的排序法,也就不喜欢别人写出的排序法,
    这是酸葡萄心理在做怪,与当年赵举人之流不许Q哥革命是一个道理.
    但历史的车轮是几个螳臂所挡不住的,
    世界之大,总有人会搞出点新东西出来,
    大家来共同见证这激动人心的新生事物问世,
    兴甚.
    其余就不必苛求了吧?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 19:21:465楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 19:29:416楼 得分:0
    不好意思,没看出来有什么新意。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 19:32:137楼 得分:0
    仔细看了一下,蛮有思想的
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 19:36:408楼 得分:0
    这个似乎在哪本书上见过
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-16 19:41:469楼 得分:0
    总结一下我的理解,楼主已经说得够清楚了,

    楼主的意思是说,

    在对一个集合进行排序的过程中,"站错位置"的数据(数值与其位置不匹配)的情况
    不会是孤立发生的,而它将涉及到一个相对封闭的子集,发现这种子集并将

    其每个成员逐一放到适当的位置后,继续向后检测直到检测完整个集合为止.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 00:17:2010楼 得分:0
    楼上ProjectDD的理解很对,我这样理解楼主的算法:

    一组n个无序的数据,其中有很多数据站错位置,这些站错位置的数据可以分成很多个的最小等价类,

    等价类的定义是,每个数据的正确位置都在组内的某个数据的位置上,最小等价类是满足这种性质的个数最少的数据集合。

    例如数据d[3],d[9],d[12],d[14],d[17],这五个数中,每个数据的正确位置都在其余四个数之一的位置上,这五个数不能再少了,再少就不封闭了。

    算法把这个最小等价类复原成有序的,这样一组一组地复原。

    一次交换就让一个数据回到正确位置上,这点和选择排序类似,但是每次交换的另一个数据被交换到了最小等价类的第一个位置。

    选择排序是对确定位置,比如第二个,找它正确的数据在哪里,比如是第25个,然后交换回来,

    楼主的算法相反,对第25个数据,计算出它的正确位置是第二个,然后交换。

    选择排序其实也是对一组组的最小等价类进行复原,每次复原一次,只是复原的次序和楼主的不同。

    确定正确位置,楼主用比较计数法,选择排序用比较记录位置法,复杂度相同。

    所以我猜测,楼主这个算法的复杂度应该和选择排序相等!

    顺便说两句浅见,之所以快速排序最快,是因为左右两部分的数据不再互相比较,而是内部互相比较,大幅度减少了比较次数,楼主算法的比较次数和选择排序相同,不知道这个地方是否有改进的余地,估计很难,因为交换是一次到位的,比较困难,所以引起重复比较次数多,而重复比较次数少的,往往交换次数多,例如冒泡排序,比较和交换平衡的最好的,就是快速算法了,一个数据一般要交换多次才到达正确位置,虽然如此,这给比较带来了灵活性,结果重复比较少,整体效果最快。

    佩服楼主的独立思考和创新精神!不过好像楼主没怎么学数据结构和算法,建议楼主下功夫学学,你一定会为那些经典算法的智慧巧妙击节赞叹,三月不知肉味,继承前人的成果,站在巨人的肩上,你才能做出真正有价值的研究!


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 07:17:2811楼 得分:0
    故事讲的很生动,很有文采
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 09:19:1012楼 得分:0
    姑且不讨论程序的效率,它的正确性都不能保证;

    lz你测试一下这个数据:
    1 0 3 2 5 4 7 6 9 8
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 09:55:2013楼 得分:0
    O(n*n)的算法.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 10:12:0514楼 得分:0
        我哥是编程高手,他看了此排序法后提出了一个观点,很有高度:他认为这个排序法实质上就是将一个混乱的数组进行复原。一个数据混乱的待排序数组可以视为是从一个有序数组通过数据交换一步步变来的,此排序法的算法过程其实就是沿着有序数组变乱的过程一步步逆行还原回去,直到还原回原来的那个有序数组。
        有序数组在变乱的过程中是一组组进行的,即随着变乱的数据逐渐增多,这些错位数据相互间构成了一个错位链,此错位链有必然闭合的特性,当此错位链一闭合就构成了一个错位环,此时环内的错位数据就组成了一个错位小组。随着数据交换的不断进行,错位数据不停的增多,他们将逐次组成一个个大小不一的错位数据小组,此种小组最少包含两个数据,也就是说任一个有大量错位数据的数组中决不会存在一个单独的与其他错位数据毫无关系的错位数据,单蹦一个的必然是站对位置的数据。
        此排序法在排序时就是沿着上述有序数组变乱的过程逆行还原回去,只不过它首先开始处理的错位数据小组不一定是最先形成的错位数据小组。

       
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 10:12:5615楼 得分:0
      研究排序法很难,因为前人已备述矣,要想出新只有一条路,就是找出现存所有排序法的一个共同的特点,然后突破此点,也许就可以见到曙光。
        纵观现存所有的排序法,我发现他们有一个共同点:就是没有对待排序数组内的错位数据的分布规律进行分析。
        我不知道这是为什么,也许是一个疏忽。但我认为分析混乱数组内错位数据的分布规律很有必要,因为弄清了这个规律也就弄清了一个有序数组变乱的过程,然后设计一个算法将此变乱过程逆行还原回去,这无论如何都应当是一个合理有效的排序算法。


       
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dlyme
    • 等级:
    发表于:2008-01-17 10:18:1716楼 得分:0
    的确是O(n^2)的低级排序算法。要通过与后面所有元素进行比较才能确定某个元素的排名,这样从本质上和冒泡法相比不会有质的区别。

    比如对于这样一个例子:10, 1, 2, 3, 4, 5, 6, 7, 8, 9,实际上它是有序数组循环右移了一位。
    如果用冒泡法,比较次数为45次,交换次数为9次;
    如果用楼主的方法,比较次数为81次,交换次数为9次;
    这种情况下楼主的办法与冒泡法相比没有任何优势。

    实际上冒泡法并不是个多么高效的算法,书上介绍得最多是因为它浅显易懂,适合初学者理解。比冒泡法好一点又能说明你的算法有多优秀么?随机生成一些大数组,用各种排序算法跑一下,孰优孰劣立刻就见分晓了。

    排序的算法实际上有很多,相信大家都有过很多稀奇古怪的想法,验证一下实践一下对自己的学习提高是很有帮助的。想法很有意思,但非要说有多优秀,恕我不敢苟同。您可以自己去当皇帝,但大家就不陪着您当太监了:)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 10:20:5517楼 得分:0
    tailzhou
    尾巴
    等 级:
    发表于:2008-01-17 09:19:1012楼 得分:0
    姑且不讨论程序的效率,它的正确性都不能保证;

    lz你测试一下这个数据:
    1  0  3  2  5  4  7  6  9  8



    真的不能保证
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 10:26:5618楼 得分:0
    楼主根本就不是在排序,是在玩游戏
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 10:43:0519楼 得分:0
    楼主,你知道选择排序吗?选择排序就是通过交换移到最终位置,看了一下,你的排序效率连直接选择排序都不如,没人会反对搞发明,但也要看看是不是自己搞的如何,直接选择排序比你的好,好在不需再在已排序的有序表中去比较,而你已排到最终位置的是散列,这就是这两种方法的区别,
    我想也不能强求别人接受把改更差的还叫发明吧。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 10:54:0720楼 得分:0
    借LZ的贴我也发明一个排序算法,效率会更高一些。

    //依次比较相邻两个数
    if(a[i] < a[i+1])then
    // 进行交换
    endif
    // 直到没有任何数据交换
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 11:12:3121楼 得分:0
    农民造飞机! 别人还飞上去了呢!
    萝卜白菜各有所爱!

    希望搂在那天能造出航天飞机!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 11:13:0422楼 得分:0
    lz你按12楼测试了吗?已排到最终位置的是散列,我看/*  计算当前数据在数组里的排名  */ 还得全部遍历一遍才能确保计算准确。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 11:22:2223楼 得分:0
    代码确实有误:
    1  0  3  2  5  4  7  6  9  8
    上述数组确实排不出来。
    但算法没错,问题出在程序里控制大for()循环的参数i的上限写错,
    若数组的长度为N,那么i应当小于2N-1,而不是N-1。

    抱歉,赶巧最近电脑坏了,代码没上机运行就急忙发出来了,
    调试好的代码尽快发上来。

    但若改成i <(2N-1),效率差了很多。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 11:29:1424楼 得分:0
    问题不出在求名次时没有遍历,因为排序的当前位置之前的数据是有序的,从当前位置向后算排名没有错,
    关键是当前数据的排名的起始值要等于当前位置,就是这一行代码:order = j;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lbaby
    • 等级:
    发表于:2008-01-17 11:49:5325楼 得分:0
    。。。
    为啥不去看看人家的flashsort ?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 11:50:5926楼 得分:0
    效能不能保证啊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 12:08:2327楼 得分:0
    就是选择排序的退化版本,你以为换了个马甲我就不认得了啊?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 12:57:2628楼 得分:0
    [size=24px]张大哥, 年纪大了, 不适合拿编程当工作了,平时娱乐一下还可以。

    不过我看你还不如写小说好了, 中国还没有好的科普科幻作品呢[/size]
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-17 13:10:4129楼 得分:0
    mark下
    很久没有看算法了~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友