C++版本的希尔排序

前面三种排序算法(冒泡、选择以及插入排序)的时间复杂度都是O( n2 ),相对来说性能最好的是插入排序,在元素个数少,且原序列基本有序的前提下,是非常高效的!所以对于人一个无序序列,我们可以认为的制造上述条件:

  • 元素个数少—分组
  • 基本有序—按照增量进行分组

这样将相距某个增量的众多元素组成一个子序列,然后在子序列内部分别进行直接插入排序,得到的序列就是所谓的基本有序序列,之后就可以按照增量为1进行插入排序即可完成排序。

希尔排序的时间复杂度突破O( n2 ),是O( n3/2 )。

希尔排序由于使用了跳跃式的比较和交换,是不稳定的排序算法。

关于MarkDown的数学公式参见:
http://www.cnblogs.com/mfrbuaa/p/4882005.html

关于如何选取增量目前没有标准答案,业界使用迭代的方法,求取每次循环的增量,迭代公式是:inc = inc/3 + 1,inc的初始值是所有元素的个数。

#include <iostream>
using namespace std;

#define MAXSIZE 100
typedef int Status;

#define OK  1
#define ERROR 0
#define TRUE  1
#define FALSE 0

template <typename T>
class SqList
{
public:
    T r[MAXSIZE+1];
    int length;
public:
    SqList(T * var,int len);
    SqList();
    void printList();

    Status swapElement(int i, int j);

    void ShellSort();
};

template <typename T>
SqList<T>::SqList(T * var,int len)
{
    length = len/sizeof(T);
    memcpy(&(r[1]), var, len);
}

template <typename T>
SqList<T>::SqList()
{
    memset(this, 0, sizeof(SqList));
}

template <typename T>
Status SqList<T>::swapElement(int i,int j)
{
    T tmp =this->r[i];
    this->r[i] = this->r[j];
    this->r[j] = tmp;
    return OK;
}

template <typename T>
void SqList<T>::printList()
{
    for (int i = 1; i <= length; i++)
    {
        cout << this->r[i] << "\t";
    }
    cout << endl;
}


/************************************************************************/
/* 希尔排序                                                                     */
/************************************************************************/
template <typename T>
void SqList<T>::ShellSort()
{
    int i, j;
    int inc = length;

    do //do-while循环主要是用来调节增量
        //每调节一次增量代表越来越趋向基本有序
    {
        inc = inc / 3 + 1;//业界常用迭代公式--增量越来越小,
                            //每一个分组的元素越来越多

        /*分组里面进行插入排序--默认分组的第一个元素已经排好序*/
        for (i = inc + 1; i <= length;i++)//i从第inc+1开始(第一个分组的第二个元素)
                                        //然后依次遍历后面的元素,他们相应是每一个分组的第二个元素
        {
            if (r[i]<r[i-inc])//如果分组的第二个元素比第一个元素小--
                            //代表需要移动分组里面已经排好序的元素--
                            //挪出位置以便给当前元素使用
            {
                r[0] = r[i];//哨兵--缓存当前元素
                for (j = i - inc; j > 0 && r[j] > r[0]; j -= inc)//分组里面移动元素--按照增量调节下标
                {
                    r[j + inc] = r[j];//向后移动
                }
                r[j + inc] = r[0];//在相应位置插入哨兵--完成插入排序
            }
        }
    } while (inc > 1);//增量序列的最后一个增量必须等于1--等于1的时候跳跃式的插入排序--希尔排序完毕
}

int main(void)
{
    int myList[9] = {90,10,50,80,30,70,40,60,20};
    SqList<int> list(myList,sizeof(myList));

    cout << "before sort:"<< endl;
    list.printList();

    list.ShellSort();
    cout << "after sort:" << endl;
    list.printList();

    cout<<"Hello!"<<endl;
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值