希尔排序
基本概念
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。
希尔排序是基于插入排序的性质而改进的排序算法:
1.首先插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;所以插入排序可能会引起多次大范围的连续的数据整体移动。
2.希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
算法描述:
1.首先选定一个增量值(一般设置为数据个数的一半,可自行设置)。
2.根据增量值,将数据分为若干个子序列。
3.对每个子序列进行插入排序。
4.减小增量值(一般是上一个增量之的一半),并重复以上步骤,直到增量值为1.
注意:增量取半只是一种常用的方法而已,不是最好的取值方式。具体哪种增量取值方式更优还需大家自行研究。
举例图示
从下标为gap的数据开始,与它前面第gap个数比较
1.数组arr[3] 与arr[0]做插入排序
2.arr[4]与arr[1]插入排序
3.arr[5]与arr[2]插入排序
4.arr[6]与arr[3]与arr[0]插入排序
5.arr[7]与arr[4]与arr[1]插入排序
…
直到最后一个元素,一遍后再减小间隔gap,重复上述操作。
当gap为1时,绝大多数的数据已经相对有序了,再进行最后一次直接插入排序,则整个数组排序完成。
代码实现:
/*
* int *arr 待排序数组
* int size 待排序数组大小
* int mode 排序方式:0为从小到大、非0为从大到小
*/
void ShellSort(int *arr, int size, int mode)
{
int gap = (size-1)/2;//gap间隔
int i,j;
for(;gap > 0;gap/=2)//减小间隔
{
for(i = gap;i < size;i++){//从第gap个开始
int temp = arr[i];//保存一下当前数据
if(mode){
for(j = i-gap;j >= 0 && arr[j] < temp;j-=gap){//对前面每gap个做插入排序
arr[j+gap] = arr[j];
}
}
else{
for(j = i-gap;j >= 0 && arr[j] > temp;j-=gap){
arr[j+gap] = arr[j];
}
}
arr[j+gap] = temp;
}
}
}
稳定性:在排序过程中由于是跳跃式排序,相等的数据位置可能会发生变化,所以是不稳定的
时间复杂度:
最好的情况与数据及增量间隔的选取有关,
最坏的情况:O(N*logN)
空间复杂度:O(1)