您的位置:首页 > 其它

插入排序的改进算法-希尔排序

2013-04-07 11:11 274 查看
  希尔排序(Shell's Sort)又称缩小增量排序,类属于插入排序。考虑到直接插入排序得一下特点:

(1)在待排序数基本有序情况下排序效率大大提高;

(2)在n很小时,其排序效率也很高。

基于以上考虑,对直接插入排序进行改进,并得出希尔排序。其基本思想为:先将整个待排序记录序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序时”,再对全体记录进行一次插入排序。

这里的子序列是通过一个增量得到的,每一次赋予不同的增量,则得到不同的子序列组(分别对子序列进行直接插入排序就称作一次希尔插入排序,注意,实际代码中并不是依次排好一个自序列之后再排下一个这样效率低,而是依次扫描每一个子序列的元素即同时对各子序列排序)。这样将该增量逐渐递减为1便最终得到的子序列组就是其本身。

此时,问题的关键就在于增量序列delta[t]了,其个数和值都将影响排序效果。已有的结论为:当delta[k]=2t-k+1-1,1≤k≤t≤log2(n+1)时其时间复杂度为O(n3/2).另外增量序列还有其他各种取法。

另外,从排序过程可知,希尔排序是一种不稳定的排序算法。

对此,源码如下:

#include <iostream>
#include <time.h>
#include <math.h>
#include <cstdlib>
#include <fstream>
#include <stdio.h>

using namespace std;

template <typename T>
void shellInsert(T &L,int dk, int length)
//对顺序表做一趟希尔排序,dk是增量值,length是待排序数组的元素个数
{
int i=0,j=0;
for (i = 1+dk; i <= length; ++i)
if (L[i] < L[i-dk])
{
L[0] = L[i]; //L[0]用来临时暂存
for (j = i-dk; j>0 && L[j]>L[0]; j -= dk)
L[j+dk] = L[j];
L[j+dk] = L[0];
}
}

template <typename T>
void shellSort(T &L, int dlta[], int t,int length)
{
for (int k = 0; k<t; ++k)
{
shellInsert(L,dlta[k],length);
/*for (int i = 1; i<=length; ++i)
cout << L[i] << ' ';
cout << endl;*/
}
}

int main()
{

srand(time(NULL));
int n,n1,i=0;
cout << "输入待排序数组的个数:";
cin >> n;
int* a = new int
;
//int* a = (int *) malloc(n*sizeof(int));
n1 = log(double(n))/log(2.0);//增量序列的大小
int* dlta = new int[n1];
//const size_t int_a_size = sizeof(a)/sizeof(a[0]);
for (i = 0; i<n1; ++i) //生成增量序列
{
dlta[i] = pow(2.0,n1-i)-1;
cout << dlta[i] << ' ';
}
cout << endl;
for (i = 1; i<n; ++i) //生成待排序数组
{
a[i] = double(rand())/(RAND_MAX+1)*n;
cout << a[i] << ' ';
}
cout << endl << endl;

shellSort(a,dlta,n1,n-1);
ofstream outs;
outs.open("shellSort.txt");
for (i = 1; i<n; ++i)
{
outs << a[i] << ' ';
if (0 == i%11)
outs << endl;
//cout << a[i] << ' ';
}
cout << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: