排序算法之 - 希尔排序(基于选择排序,插入排序)

    之前说的选择,插入,冒泡三种基本排序,时间复杂度都为O平方,直到希尔排序的出现,打破了O平方的魔咒.希尔排序的基本思想我理解是属于分而治之,把一个无序序列划分为若干个子序列,再分别对这写子序列使用三种基本排序方法进行排序.
下边直接看示意图:
要排的序列为 int array[] = {12,32,2,4,6,54,34,76,89,32,14};排序为升序排序
第一次划分:假设间隔d = 3,那么可以划分为{12,32,2,4,6,54,34,76,89,32,14}得到三个子序列(一个颜色集合为一个子序列)
接着对三个子序列按基本排序法排序,得到{4,6,2,12,14,54,32,32,89,34,76},从这里我们可以看到,这个序列已经基本有序.
第二次划分:缩减间隔d=2,那么可划分为{4,6,2,12,14,54,32,32,89,34,76} 得到两个子序列,然后对这两个子序列按基本排序法排序,
得到  {2,6,4,12,14,32,32,34,76,54,89}
第三次划分:缩减间隔d=1,划分为 {2,6,4,12,14,32,32,34,76,54,89},到了这里,整个序列基本已经排好了,只需要在使用一次基本排序,做少量的元素交换,便可完成序列的排序.

    以上便是希尔排序的基本思想,先分而治之,划分为各个子序列,各自排序,之后只需要统一做少量的交换工作,便可完成整个序列的排序.下边来看看代码,这里我分别使用选择排序,插入排序来实现
 

#include <iostream>
#include <string.h>
#include <errno.h>
#include <stdio.h>

using namespace std;

//需要注意的是,这里的类模板需要放在头文件中去实现,这里为了直观,直接放这里了
template <typename T>
class Sort : public Object
{
private:
static void swap(T& nLeft, T& nRight)
{
    T tmp = nLeft;
    nLeft = nRight;
    nRight = tmp;
}
public:
//基于选择排序的希尔排序
static void SelectShell(T* nArray, int nLen, bool Min2Max = true)
{
    int d = nLen;
    while(d > 1)
    {
        d = d/3 +1;
        int count = 0;
        while(count<d)
        {
            for(int i=count; i<nLen; i+=d)
            {                
                int index = i;

                for(int j=i+d; j<nLen; j+=d)
                {
                    if( Min2Max ? (nArray[index] > nArray[j]):(nArray[index] < nArray[j]))
                    {
                        index = j;
                    }
                }
                if(index != i)
                {
                    swap(nArray[index], nArray[i]);
                }
            } 
            count++;
        }                   
    }
}
//基于插入排序的希尔排序
static void InsertShell(T* nArray, int nLen, bool Min2Max = true)
{
    int d = nLen;
    while(d > 1)
    {
        d = d/3 + 1;
        int count = 0;
        while(count < d)
        {
            for(int i=count; i<nLen; i+=d)
            {
                int index = i;
                T e = nArray[index];
                for(int j=i; j>=0; j-=d)
                {
                    if( Min2Max ? (e < nArray[j]):(e> nArray[j]))
                    {
                        nArray[j+d] = nArray[j];
                        index = j;
                    }
                }
                if(index != i)
                {
                    nArray[index] = e;
                }
            }
            count++;
        }        
    }
}
};

int main(int argc, char* argv[])
{
    int array[] = {12,32,2,4,6,54,13,34,25,87,76,89,32,14,23};
    int len = sizeof(array)/sizeof(int);

    Sort<int>::InsertShell(array, len);

    for(int i=0; i<len; i++)
    {
        cout << array[i] << " ";
    }
    cout << endl;
    Sort<int>::SelectShellShell(array, len, false);

    for(int i=0; i<len; i++)
    {
        cout << array[i] << " ";
    }
    cout << endl;
    return 0;
}

main测试函数中分别用了基于插入排序与基于选择排序的希尔排序来测试,一个测升序,一个测降序,其结果是符合我们的预期的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值