希尔排序
扫描二维码
随时随地手机看文章
1、希尔排序是对直接插入排序进行改进后增加效率的排序算法。
---- 希尔排序(Shell Sort):是插入排序的一种。因D.L.Shell于1959年提出而得名。
---- 直接插入排序的效率在某些时候是很高的,比如:
--1)我们的记录本身就是基本有序的,只需要少量的插入操作,就可以完成整个记录集的排序工作。
--2)记录数比较少的时候。
---- 思想:
先取一个小于数组长度n的整数d1(一般为n/2)作为第一个增量,把文件的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插入排序;然后取第二个增量d2<d1(一般为d1/2),重复上述的分组和排序,直至所取的增量dt=1,即所有记录放在同一组中
进行直接插入排序为止。
-- 如何将待排序的记录个数较少?将原本有大量记录数的记录进行分组,分割成若干个子序列,此时每个子序列待排序的记录个数就比较少了,然后
在这些子序列 内分别进行直接插入排序,当整个序列都基本有序时,注意只是基本有序时,再对全体记录进行一次直接插入排序。
-- 所谓的基本有序,就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间,像{2,1,3,6,4,7,5,8,9}这样的可以称为基本有序了。
-- 跳跃分割的策略:将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。
2、希尔排序算法
例子1:
#includeusing namespace std; #define dim(x) (sizeof(x)/sizeof(x[0])) void swap(int *x,int *y) { int t = *x; *x = *y; *y = t; } void ShellSort(int a[],int n) { int k = n/2; //k值代表增量 while(k>=1) //当增量k值变化到0,结束循环 { for(int i = 0;i<n;i++) //将数组分成k组,然后对每组进行直接插入排序 { for(int j = i+k;j=k && a[m]<a[m-k]) { swap(&a[m],&a[m-k]); m-=k; } } } k = k/2; } } void main() { int a[] = {49,38,65,97,76,13,27}; ShellSort(a,dim(a)); for(int i=0;i<dim(a);i++) { printf("%d ",a[i]); } printf("n"); system("pause"); }
输出:
例子2:
#define MaxSize 10 //要排序数组元素的最大值,可根据需要修改 typedef struct { int r[MaxSize+1];//用于存储要排序数组,r[0]用作哨兵或临时变量 int length; //用于记录顺序表的长度 }SqList; void swap(SqList *L,int i,int j) { int t = L->r[i]; L->r[i] = L->r[j]; L->r[j] = t; } void ShellSort(SqList *L) { int i,j; int increment = L->length; do { increment = increment/3+1; for(i=increment+1;ilength;i++) //具有相同增量的元素分为一组 { if(L->r[i]r[i-increment]) { L->r[0] = L->r[i]; for(j=i-increment;j>0 && L->r[j]>L->r[0];j-=increment) { L->r[j+increment] = L->r[j];//记录后移,查找插入位置 } L->r[j+increment] = L->r[0]; } } }while(increment>1); } int main() { SqList *L = (SqList*)malloc(sizeof(SqList)); int a[MaxSize] = {9,1,5,8,3,7,4,6,2,0}; for(int i=0;ir[i+1] = a[i]; } L->length = MaxSize; ShellSort(L); cout<<"排序后的序列如下:"<<endl; for(int i=1;ilength;i++) { cout<r[i]<<" "; } cout<<endl; system("pause"); return 0; }