希尔排序属于高级的排序方法,接下来阐述一下该排序算法的思想。
(1) 希尔排序的思想
希尔排序的思想就是:定义一个呈递减变化的步长gap,假设数组长度为size,最开始定义的步长为gap=size/2,并从第0个元素开始,将数组中间隔为gap的元素构成子数组,共构成gap个子数组,之后对每个子数组进行排序(排序方法任意),此时第一步就算完成了;然后定义第二步的步长为gap=gap/2,并做与第一步相同的操作;以此类推,每次取步长为gap=gap/2,直到对gap为1的数组进行排序后,整个排序过程结束。
为了更好地理解该排序算法的思想,我们来看下面的图片:
从上图可以知道,原始数组为:10 8 6 20 4 3 22 1 0 15 16,以排升序为例,接下来进行分步操作。
第一步:由于数组长度size=11,故gap=11/2=5,故共分为5个子数组,分别对这5个子数组进行排序后,数组变化为:3 8 1 0 4 10 22 6 20 15 16。
第二步:由于第一步的gap为5,故该步骤的gap=5/2=2,但可以看到图片上的gap为3,这是由于图片作者失误导致的,在后面的算法实现中,本文作者不会出现类似的错误,读者大可放心。但这不影响我们来掌握希尔排序的思想,我们根据图片中的gap为3,故共分成3个子数组,分别对这3个子数组进行排序后,数组变化为:0 4 1 3 6 10 15 8 20 22 16。
第三步:由于第二步的gap为3,故该步骤的gap=3/2=1,故共分为1个子数组,对这1个子数组进行排序后,数组变化为:0 1 3 4 6 8 10 15 16 20 22。
(2) 希尔排序的实现
本次排序算法采用C++模版编程来实现,且对每个子数组采用冒泡排序进行排序。
#include <iostream>
#include <iterator>
using namespace std;
template<class T,size_t N>
void PrintArr(T (&arr)[N])
{
copy(arr,arr+N,ostream_iterator<T>(cout," "));
cout << endl;
}
template<class T,size_t N>
void ShellSort(T (&arr)[N])
{
size_t gap(N);
size_t end;
size_t step;
while(gap > 1) {
step = 0;
gap /= 2;
do {
size_t i(step);
end = N;
while(end > gap) {
for(; i < end; i += gap) {
if(arr[i] > arr[i+gap] and (i+gap) < N) {
swap(arr[i],arr[i+gap]);
PrintArr(arr);
}
}
end -= gap;
i = step;
}
step++;
} while(step < gap);
}
}
int main()
{
int arr[] = {10,8,6,20,4,3,22,1,0,15,16};
// int arr[] = {10,9,8,7,6,5,4,3,2,1};
// int arr[] = {1,2,3,4,5,6,7,8,9,10};
cout << "The init:" << endl;
PrintArr(arr);
cout << "The sort:" << endl;
ShellSort(arr);
cout << "The final:" << endl;
PrintArr(arr);
}
原始数组为:10 8 6 20 4 3 22 1 0 15 16
程序运行结果为:0 1 3 4 6 8 10 15 16 20 22