梳排序也属于简单的排序算法,也是一种不稳定的排序方法。在讲述梳排序的思想之前,先介绍一下与该排序有关的一个关键常量:递减率;该常量为固定值:1.3。该常量是由原作者Wlodzimierz Dobosiewicz以随机数做实验得到的,对于此大可不必纠结,直接用就行。
(1) 梳排序的思想
梳排序的思想就是:最开始的时候先定义一个步长,该步长为数组的长度除以1.3(注意:直接用整型除即可,例如数组长度为5,则开始的步长为5/1.3=3),然后从第0个元素开始,跟距离当前元素为步长大小的元素进行比较(例如,开始步长为3,所以第0个元素跟第3个元素进行比较),若前者大于后者就进行交换,否则继续往后进行比较,直到比较到最后一个元素为止;完成前面的操作后,第一步就算完成了,接下来从第二步开始,将第一步的步长除以1.3(第一步的例子中步长为3,故第二步的步长为3/1.3=2)后得到新的步长,之后参照第一步的做法进行比较,直到比较到最后一个元素为止;接下来讲述一下约束条件,当步长小于1的时候,不再进行比较操作。此外,稍微提一下,该例子以排升序为例,排降序与其类似,读者参照后可自行编写。
所以,从上述的思想中,我们知道:递减率其实就是所要比较的两个元素的间距的递减率。为了更好地理解该算法的思想,我们来看以下图片:
从上图可以知道,原始数组为:41 11 7 16 25 4 23 32 31 22 9 1 22 3 7 31 6 10,以排升序为例,接下来进行分步操作。
第一步:数组长度为19,故第一步的步长为19/1.3=14。故第0个元素41与第14个元素3进行比较,41大于3,进行交换;同理,第1个元素11与第15个元素7进行比较,11大于7,进行交换;以此类推,比较到最后一个元素后,此时数组变成:3 7 18 6 10 25 4 23 32 31 22 9 1 22 41 11 31 7 16。
第二步:第一步的步长为14,故第二步的步长为14/1.3=10。故第0个元素3与第10个元素22进行比较,3小于10,不进行交换;同理,第1个元素7与第11个元素9进行比较,7小于9,不进行交换;以此类推,比较到最后一个元素后,此时数组变成:3 7 1 6 10 11 4 7 16 31 22 9 18 22 41 25 31 23 32。
第三步:第二步的步长为10,故第三步的步长为10/1.3=7。故第0个元素3与第7个元素7进行比较,3小于7,不进行交换;同理,第1个元素7与第8个元素16进行比较,7小于9,不进行交换;以此类推,比较到最后一个元素后,此时数组变成:3 7 1 6 9 11 4 7 16 31 22 10 18 22 41 25 31 23 32。
第四步:第三步的步长为10,故第四步的步长为10/1.3=7。故第0个元素3与第7个元素7进行比较,3小于7,不进行交换;同理,第1个元素7与第8个元素16进行比较,7小于9,不进行交换;以此类推,比较到最后一个元素后,此时数组变成:3 7 1 6 9 11 4 7 16 31 22 10 18 22 41 25 31 23 32。
第五步;第四步的步长为7,故第五步的步长为7/1.3=5。故第0个元素3与第5个元素11进行比较,3小于11,不进行交换;同理,第1个元素7与第6个元素4进行比较,7大于4,进行交换;以此类推,比较到最后一个元素后,此时数组变成:3 4 1 6 9 11 7 7 16 31 22 10 18 22 41 25 31 23 32。
(2) 梳排序的实现
本次排序算法采用C++模版编程来实现。
#include <iostream>
#include <iterator>
#include <iomanip>
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 CombSort(T (&arr)[N])
{
size_t gap(N);
while(gap > 0) {
gap /= 1.3;
for(size_t i = 0; i+gap < N; i++) {
if(arr[i] > arr[i+gap]) {
swap(arr[i],arr[i+gap]);
}
}
PrintArr(arr);
}
}
template<class SortFunc>
void Test(SortFunc sort)
{
int arr[]= {41,11,18,7,16,25,4,23,32,31,22,9,1,22,3,7,31,6,10};
PrintArr(arr);
sort(arr);
cout << "The final:" << endl;
PrintArr(arr);
}
原始数组为:41 11 7 16 25 4 23 32 31 22 9 1 22 3 7 31 6 10
程序运行结果为:1 3 4 6 7 7 9 10 11 16 18 22 22 23 25 25 31 31 32 41