希尔排序
定义
建立在少量增量的基础上、是针对直接插入排序算法的改进
思想:
先对原始数组各部分进行排序,待数组中元素基本有序,再对数组进行一次排序。若子数组已经排好序,此时的数组相对初始数组已经非常接近一个有序数组的最好情况了。它主要是建立在少量的增量上面的。若增量为5,则对在0,5,10位置上的元素,1,6上的元素,2,7上的元素进行排序,然后增量减少。比如减少至3,则对上次排序好的数组的0,3,6,9进行排序,对1,4,7上的元素进行排序,以此类推。
其中增量的选择是最为重要的。我们应该采用的是混合效应。而且最后一个增量必须为1,才能保证数组是有序的。若增量为2,则掉到交换的次数会快速地减少。通常采用的增量序列如下:
hi=1
hi+1=3*h+1
运行结果:
效率:
在分组中采用的是插入排序,其效能大于插入。不是稳定的排序。因为增量的原因。不需要大量的辅助空间。
代码:
template<class T>//进行希尔排序
void ShellSort<T>::Shell_Sort(T *ShellSortArray,int length)
{
//主要思想:1、进行增量的设置,尽管没有令人信服的增量设置,但是我们要防止4-,2-这样的增量,如此混合效应丢失
//2、对分组的数据进行插入排序
//3、一直到增量为1-
//插入排序的要点,是比较前面的元素,若比比较的元素大,则前面的元素赋值给后面的元素
//一直到不大于比比较元素时,将比较元素插入
int increaseNumIndex=0;//增量的索引
int h=1;//增量
int increase[20];//增量数组
int k=0;
while(h<length)
{
increase[increaseNumIndex]=h;
h=h*3+1;//设置增量的值
increaseNumIndex++;
}
increaseNumIndex--;
while(increaseNumIndex>=0)
{
h=increase[increaseNumIndex];//获得增量
for(int i=0;i<h;i++)
{
for (int j=i;j<length;j+=h)
{
k=j;
T temp=*(ShellSortArray+k);//后面采用插入排序
while((k-h)>=0&&temp<*(ShellSortArray+(k-h)))
{
*(ShellSortArray+k)=*(ShellSortArray+(k-h));
k=k-h;
}
*(ShellSortArray+k)=temp;
}
}
cout<<"增量为:"<<h<<endl;
for (int i=0;i<10;i++)
{
cout<<*(ShellSortArray+i)<<" ";
}
cout<<endl;
increaseNumIndex--;//继续更小的增量
}
}
小结:1、主要比较的对象,是当前的数组中对应的元素
2、采用插入排序,若是索引上元素比要比较的元素大,则index-增量h。