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

  希尔排序(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[n];
    //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;
}

 

    

posted @ 2013-04-07 11:11  busyfruit  阅读(578)  评论(0编辑  收藏  举报