数据结构-希尔排序
1、希尔排序
也称 递减增量排序算法,是 插入排序 的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
-
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到 线性排序 的效率;
-
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
步长的选择是希尔排序的重要部分。
只要最终步长为1任何步长序列都可以工作。
算法最开始以一定的步长进行排序。
然后会继续以一定步长进行排序,最终算法以步长为1进行排序。
当步长为1时,算法变为普通插入排序,这就保证了数据一定会被排序。
插入排序的算法步骤如下:
-
定义一个用来分割的步长;
-
按步长的长度K,对数组进行K趟排序;
-
不断重复上述步骤。
简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。
而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。
希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。
然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。
#include <stdio.h> void InsertSort(int* p, int n) { int temp,i,j; for (i = 0; i < n; i++) { temp = p[i]; for (j = i - 1; (j >= 0) && (p[j] > temp); j--) { p[j + 1] = p[j]; } p[j + 1] = temp; } } void ShellInsertSort(int* p, int n) { int temp, i, j; int gap = n; do { gap = gap / 3 + 1; //对步长进行操作,包括不同步长下的循环,直到步长为1时 for (i = gap; i < n; i++) { if (p[i] < p[i - gap]) //这里是一个小技巧,判断当前是否有序,在无序的情况下才需要插入操作! { temp = p[i]; //设置哨兵,就是要插入的元素 for (j = i - gap; (j >= 0) && (p[j] > temp); j-=gap) //j为哨兵前一个需要比较的元素 { p[j + gap] = p[j]; } p[j + gap] = temp; } } } while (gap>1); } int main() { int a[] = { 4,2,5,6,7,8,3,1,9 }; ShellInsertSort(a,9); printf_s("排序后:\n"); for (int i = 0; i < 9; i++) { printf_s("%d ", a[i]); } return 1; }