我们都知道,当原序列基本已经有序了的时候,采用插入排序的话其效率可以达到线性。但一般情况下插入排序的效率并不高。而希尔排序正是对它的一种改进。
希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。
下面具体来说说希尔排序的思想:
假设一个数组如下:2 43 12 32 9 10 8 7 45 3, 此时数组长度 len = 10;
第一步:
此时 gap = 10 / 2 = 5。所以此时进行排序的组合为:
即分成了5组,每组为形同颜色的两个,每组内部采用直接插入排序的方法,则排序完后的序列如下:
第二步:
此时gap = 5 / 2 = 2。所以此时进行排序的组合为:
即分成了2组,同样,颜色相同的为一组,各组内部进行直接排序,排序完后的序列如下:
第三步:
此时 gap = 2 / 2 = 1。所以此时进行排序的组合为:
因为此时gap等于一,相当于对一个排序情况已经很不错了的序列进行排序,所以直接排序后的序列如下:
第四步:
此时 GAP = 1 / 2 = 0,退出排序。
所以最终的序列变成了这个有序序列。
下面是程序实现:
#include <iostream> #include <stdio.h> using namespace std; void shellSort(int* arrayL, int len) { //步长变换 for (int gap = len / 2; gap > 0; gap /= 2) { //处理每个组 for (int i = 0; i != gap; i++) { //每个组内部进行直接插入排序 for (int j = i + gap; j < len; j += gap) { if (arrayL[j] < arrayL[j - gap]) { int k = j - gap; int temp = arrayL[j]; //直接插入排序 while(k >= 0 && arrayL[k] > temp) { arrayL[k + gap] = arrayL[k]; k -= gap; } arrayL[k + gap] = temp; } } } } } void output(int* arrayL, int len) { for (int i = 0; i != len; i++) printf("%d ", arrayL[i]); } int main(int argc, char const *argv[]) { cout << "Enter the length of the array: "; int lenOfArray; scanf("%d", &lenOfArray); cout << "Ehter the number to sort: "; int *arrayL = new int[lenOfArray]; for (int i = 0; i != lenOfArray; i++) scanf("%d", &arrayL[i]); shellSort(arrayL, lenOfArray); output(arrayL, lenOfArray);
delete []arrayL;
return 0; }