希尔排序基本思想
基本思想
希尔排序(Shell Sort)又称为“缩小增量排序”。是1959年由D.L.Shell提出来的。该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
具体做法:首先确定一组增量d0,d1,d2,d3,...,dt-1()其中n>d0>d1>...>dt-1=1),对于i=0,1,2,...,t-1,依次进行下面的各趟处理:根据当前增量di将n个元素分成di个组,每组中元素的下标相隔为di;再对各组中元素进行直接插入排序.
2、下面给出希尔排序算法的执行过程。
(1)采用希尔排序法排序的各趟的结果如下:
初始:503,17,512,908,170,897,275,653,426,154,509,612,677,765,703,94
第1趟{d1=8}:426,17,509,612,170,765,275,94,503,154,512,908,677,897,703,653
第2趟(d2=4):170,17,275,94,426,154,509,612,503,765,512,653,677,897,703,908
第3趟(d3=2):170,17,275,94,426,154,503,612,509,653,512,765,677,897,703,908
第4趟(d1=1):17,94,154,170,275,426,503,509,512,612,653,677,703,765,897,908
(2)例如,n=8,数组a的八个元素分别为:17,3,30,25,14,17,20,9。
基本思想
希尔排序(Shell Sort)又称为“缩小增量排序”。是1959年由D.L.Shell提出来的。该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
具体做法:首先确定一组增量d0,d1,d2,d3,...,dt-1()其中n>d0>d1>...>dt-1=1),对于i=0,1,2,...,t-1,依次进行下面的各趟处理:根据当前增量di将n个元素分成di个组,每组中元素的下标相隔为di;再对各组中元素进行直接插入排序.
2、下面给出希尔排序算法的执行过程。
(1)采用希尔排序法排序的各趟的结果如下:
初始:503,17,512,908,170,897,275,653,426,154,509,612,677,765,703,94
第1趟{d1=8}:426,17,509,612,170,765,275,94,503,154,512,908,677,897,703,653
第2趟(d2=4):170,17,275,94,426,154,509,612,503,765,512,653,677,897,703,908
第3趟(d3=2):170,17,275,94,426,154,503,612,509,653,512,765,677,897,703,908
第4趟(d1=1):17,94,154,170,275,426,503,509,512,612,653,677,703,765,897,908
(2)例如,n=8,数组a的八个元素分别为:17,3,30,25,14,17,20,9。
C语言源代码:
#include <stdio.h>
void shSort(int a[], int n);
int main(void)
{
int i;
int a[] = {503,17,512,908,170,897,275,653,426,154,509,612,677,765,703,94};
shSort(a, 16);
for(i = 0; i < 16; i++)
{
printf("%-5d", a[i]);
}
return 0;
}
void shSort(int a[], int n)
{
int d, i, j, x;
d = n / 2;
while(d >= 1)
{
/*
从数组下标为d的元素开始与前一个数组元素比较
直到数组的最后一个元素
*/
for (i = d; i < n; i++)
{
//获取数组中要比较的两个数值中的后一个数值
x = a[i];
//获取数组中要比较的前一个数值的下标
j = i - d;
/*
首先要保证得到的下标大于等于0,也就是这个数值在数组中存在
其次,后一个数值比前一个数值大,则交换彼此的值
*/
while(j >= 0 && a[j] > x)
{
//将序列中前面大的数值赋给后面小的数值存放的空间
a[j+d] = a[j];
/*
这里为什么需要使用j-d
因为j = i -d;
当需要前后数值进行交换时,就必须将下标为j
的数值存放到j+d里面去,下标j里面需存放下标为j+d(即临时变量x)的数值,
当不需要交换数值时,下标j+d的数值就是其自身。
j = j -d + d = j = i - d,保证了无论是否发生交换,
a[j+d] = x都有通用性。
*/
j = j - d;
}
/*
保存数据
*/
a[j+d] = x;
}
d /= 2; //缩小增量
}
}
结果图片: