本博文源于浙江大学《数据结构》,今天姥姥讲解希尔排序。希尔排序是对插入排序增量序列的扩展,如何更好的加快排序的速度,有以下的结论需要熟知:
希尔排序复杂度分析:
最好和最坏都在 T=O(N^2)
希尔排序不是稳定的,可能把相同元素位置换掉
算法特点:
- 记录跳跃式地移动导致排序方法是不稳定的
- 只能用于顺序结构,不能用于链式结构。
- 增量序列可以有各种取法,但应该使增量序列值没有除1之外的公因子,并且最后一个增量必须等于1.
- 记录总的比较次数和移动次数都比直接插入排序排序要少,当n越大,效果明显,所以希尔排序适合初始无序,n较大时的情况
因此,引入增量序列对希尔排序进行优化是显地非常有必要的。
增量序列
图片是对增量序列的优化,也可以看到在间隔排序后,最后一个1间隔排序的次数大大减少,显得希尔排序看起来非常优秀,因此如何定义出更好的增量排序就成为大牛们的议题了。
增量序列的优化
这是一个非常囧的案例,在间隔后的排序前三躺竟然啥都没发生。太吃惊了。最后得出定理
定理1 增量元素不互质,则小增量可能根本不起作用
Hibbard增量序列
这就是对增量序列的一次改进。将增量序列进行优化。
Sedgewick增量序列
就是用第二行那个计算公式倒出增量序列的公式。也可以试试。
测试用例
int arr[5] = {5,3,1,6,2};
将整型数组里的元素进行排序,5由里面的元素进行改变,并在下面给出希尔排序的源码
源码(教科书版本)
#include<stdio.h>
typedef int ElementType;
void Print_Array(ElementType A[],int N)
{
printf("\n");
for(int i=1;i<N;i++)
printf("%d ",A[i]);
}
void ShellInsert(int arr[],int dk){
int i,j;
for(i = dk+1;i<=4;++i){
if(arr[i]<arr[i-dk]){
arr[0] = arr[i];
for(j =i-dk;j>0 && arr[0] < arr[j];j-=dk)
arr[j+dk] = arr[j];
arr[j+dk] = arr[0];
}
}
}
void ShellSort(int arr[],int dt[],int t){
for(int k=0;k<t;k++)
ShellInsert(arr,dt[k]);
}
int main()
{
int arr[5] = {5,3,1,6,2};
Print_Array(arr,5);
int dt[3]={3,2,1};
ShellSort(arr,dt,3);
Print_Array(arr,5);
return 0;
}
源码附上(优化版本)
//希尔排序
#include<stdio.h>
typedef int ElementType;
void Print_Array(ElementType A[],int N)
{
printf("\n");
for(int i=0;i<N;i++)
printf("%d ",A[i]);
}
void Shell_sort(ElementType A[], int N)
{
int D,i,Tmp,P;
for(D= N/2;D>0;D/=2) {
for(P=D;P<N;P++) {
Tmp = A[P];
for(i=P;i>=D && A[i-D]>Tmp;i-=D)
A[i] = A[i-D];
A[i] = Tmp;
}
}
}
int main()
{
int arr[5] = {5,3,1,6,2};
Print_Array(arr,5);
Shell_sort(arr,5);
Print_Array(arr,5);
return 0;
}