先声明:所有的排序我都会总结记录在博客里,最后会有一个大的cpp文件包含全部排序的代码,每个排序算法放在单独的一个namespace里面,清晰明了,并设计对数器给出测试。我会把它放到网盘供需要之人下载,见这里。 ps:所有的排序以升序为基准。测试编译器为Visual C++
希尔排序:Donald Shell发明,冲破二次时间屏障的第一批排序算法之一。但是,若干年之后才被证明。
希尔排序思想:跟插入排序思想一样,只不过是比较相距一定间隔的元素,间隔距离慢慢减小,直到最后一趟间隔为1(间隔为1就是插入排序)。所以,希尔排序又叫缩减增加排序(diminishing increment sort)。
希尔排序不稳定,也是比较类排序。
希尔排序使用一个序列 h1,h2, …, ht,叫做增量序列。增量序列很多,只需要 h1 为1即可(为1,不就是插入排序,所以插入排序就是增量序列只有一个 h1=1的希尔排序,一个特例而已)。
下面取一张图:很清楚的解释。
使用shell增量的代码:
template<typename T>
void shellsort(T* arr, int size) {
if (size <= 0)
return;
for (int k = size / 2; k >= 1; k /= 2) { // 采用shell增量序列
for (int i = k; i < size; ++i) {
T tmp = arr[i];
int j = i;
for ( ; j >= k && tmp < arr[j - k]; j -= k) { // 实际上就是间隔为 K 的插入排序
arr[j] = arr[j - k];
} //最后j位置就是tmp需在的位置
arr[j] = tmp;
}
}
}
还有其他一些出名的增量序列:Hibbard增量、最好的是{1, 5, 19, 41, 109, …}(项为9*4i - 9*2i + 1 或者为 4i - 3*2i + 1)。将其放到数组里很容易实现shellsort算法。
结果:
时间复杂度:希尔排序算法简单但分析却极其复杂。但是其性能在实践中完全可以接受,即使对于数以万计的N亦是如此。编程的简单性使得它成为对适度大量数据输入经常采用的算法。
这里截取两个定理:
时间复杂度依增量序列的不同而不同。分析太难了,不用掌握。
纸上得来终觉浅,绝知此事要躬行。