找到最快的算法,一直是计算机界的目标之一,而排序就是其中最基本的算法。什么样的排序才是最快的呢?
1.最少的比较次数,算法理论证明n个数排序,如果是基于比较的算法,至少需要 ㏒(n!) 向上取整数。下面给出小数目下,最少比较次数:
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
㏒(n!) | 0 | 1 | 3 | 5 | 7 | 10 | 13 | 16 |
2.移动次数最少,根据群论置换群理论,n个数的序列,变换到这n个数组成另一个序列,一定可以在最多n次移动内做到。
在理论的指引下,人们开始寻找这些传说中的极限。人们开始简单地完成了n=1,2,3,4的极限算法,但是当n=5时,人们长期停留在了8次比较。但是在1956年,H.B.Demuth在终于首先找到5个次7次比较的排序方法,并在他的博士论文中进行了阐述。下面就是对这个算法的C语言实现:
/* 1956年H.B.Demuth找到的5个数7次的比较方法,后来Lester Ford,Selmer Johnson归并插入排序中使用*/ /******************************************************************** * 示意图如下 * * * * [0] [1] 排序得 [0]<=[1] * * [2] [3] 排序得 [2]<=[3] * * [1] [3] 排序得 [1]<=[3] * * 此时有关系:[0]<=[3],,[2]<=[1]<=[3] * * * * [1] [4] * * _______|_______ * * | | * * [1]<=[4] [1]>[4] * * ___|___ ___|___ * * | | | | * * [0]<=[1] [0]>[1] [2]<=[4] [2]>[4] * * ① ② ③ ④ * * * * 情况①:[0][2]比较一次,[3][4]比较一次,即可确定顺序 * * 情况②:[0][4]比较一次,[0]<=[4]则[3][4]再比较一次 * * 情况③:[0][4]比较一次,[0]<=[4]则比较[0][2],否则比较[0][1] * * 情况④:[0][2]比较一次,[0]<=[2]则比较[0][4],否则比较[0][1] * * * * 伪代码如下: * * SORT([0],[1]); * * SORT([2],[3]); * * SORT([1],[3]); * * IF [1]<=[4] * * IF [0]<=[1] * * IF [0]<=[2] * * IF [3]<=[4] ① * * ELSE ② * * ELSE * * IF [3]<=[4] ③ * * ELSE ④ * * ELSE * * IF [0]<=[4] * * IF [3]<=[4] ⑤ * * ELSE ⑥ * * ELSE ⑦ * * ELSE * * IF [2]<=[4] * * IF [0]<=[4] * * IF [0]<=[2] ① * * ELSE ② * * ELSE * * IF [0]<=[1] ③ * * ELSE ④ * * ELSE * * IF [0]<=[2] * * IF [0]<=[4] ⑤ * * ELSE ⑥ * * ELSE * * IF [0]<=[1] ⑦ * * ELSE ⑧ * * 共15种情形,针对每种情形都可以有最佳移动顺序 0-8次,平均4.5次 * ********************************************************************/ /*比较[0][1]*/ if( arr[0] > arr[1]) swap(arr[0],arr[1]); /*比较[2][3]*/ if( arr[2] > arr[3]) swap(arr[2],arr[3]); /*比较[1][3]*/ if( arr[1] > arr[3]) swap(arr[1],arr[3]); if( arr[1] <= arr[4] ) { if( arr[0] <= arr[1]) { if( arr[0] <= arr[2] ) { if( arr[3] <= arr[4] ) { /* ① 正确顺序为:[0][2][1][3][4]*/ swap(arr[1],arr[2]); return 0; } else/*②正确顺序为:[0][2][1][4][3]*/ { swap(arr[1],arr[2]); swap(arr[3],arr[4]); return 0; } } else/* arr[3] >= arr[1] >= arr[0] > arr[2] */ { if( arr[3] <= arr[4])/*③正确顺序为:[2][0][1][3][4]*/ { int temp = arr[2]; arr[2] = arr[1]; arr[1] = arr[0]; arr[0] = temp; return 0; } else/*④正确顺序为:[2][0][1][4][3]*/ { int temp = arr[2]; arr[2] = arr[1]; arr[1] = arr[0]; arr[0] = temp; swap(arr[3],arr[4]); return 0; } } } else/* arr[1]<= arr[4] && arr[0] > arr[1] */ { if( arr[0] <= arr[4]) { if( arr[3] <= arr[4])/* ⑤正确顺序为[2][1][0][3][4]*/ { swap(arr[0],arr[2]); return 0; } else/* ⑥正确顺序为[2][1][0][4][3]*/ { swap(arr[0],arr[2]); swap(arr[3],arr[4]); return 0; } } else/* ⑦正确顺序为[2][1][4][0][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[0]; arr[0] = arr[2]; arr[2] = temp; return 0; } } } else/* arr[1] > arr[4] */ { if( arr[2] <= arr[4] )/* [2][4][1][3]*/ { if( arr[0] <= arr[4] ) { if( arr[0] <= arr[2])/*①正确顺序为[0][2][4][1][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[1]; arr[1] = arr[2]; arr[2] = temp; return 0; } else/*②正确顺序为[2][0][4][1][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[1]; arr[1] = arr[0]; arr[0] = arr[2]; arr[2] = temp; return 0; } } else { if( arr[0] <= arr[1] )/*③正确顺序为[2][4][0][1][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[1]; arr[1] = temp; swap(arr[0],arr[2]); return 0; } else/*④正确顺序为[2][4][1][0][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[0]; arr[0] = arr[2]; arr[2] = arr[1]; arr[1] = temp; return 0; } } } else/* [4][2][1][3] */ { if( arr[0] <= arr[2] ) { if( arr[0] <= arr[4] )/*⑤正确顺序为[0][4][2][1][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[1]; arr[1] = temp; return 0; } else/*⑥正确顺序为[4][0][2][1][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[1]; arr[1] = arr[0]; arr[0] = temp; return 0; } } else { if( arr[0] <= arr[1] )/*⑦正确顺序为[4][2][0][1][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[1]; arr[1] = arr[2]; arr[2] = arr[0]; arr[0] = temp; return 0; } else/*⑧正确顺序为[4][2][1][0][3]*/ { int temp = arr[4]; arr[4] = arr[3]; arr[3] = arr[0]; arr[0] = temp; swap(arr[1],arr[2]); return 0; } } } }
上述程序,我应经做了简单的测试,没有发现bug,比较的思想在注释中进行了详细说明。有人说,优秀的程序员都有完美情节,我们看到追求完美的带价的高昂的,程序显得异常复杂。但也正是这种不断追求完美的勇气,才让这个世界越来越美好,越来越丰富多彩,不是吗?