希尔排序(Shell Sort)

#include<bits/stdc++.h>
using namespace std;

/*
    说明:
        下面的内容全是按照升序排序来写的。 
*/ 

/*
    逆序对:
        对于下标i < j,若arr[i] > arr[j],则称arr[i]和arr[j]是一个逆序对。
        在排序过程中,最终的目的就是需要消除全部的逆序对。
    简单排序的弊端:
        在简单排序中,以交换相邻的两个元素的算法每次都仅能消除一个逆序对,
        所以提升排序效率的方法是每次交换两个元素时能消除多个逆序对。
*/

/*
    希尔排序:
        希尔排序是插入排序的改进,插入排序每次仅交换相邻的两个元素。希尔
        排序中多次调用插入排序,但排序的间隔不再是1,每趟排序交中进行交换
        的是一定间隔的排序。使其能做到交换两个元素时能消除多个逆序对。但
        是最后一趟插入排序的间隔一定是1,也就是说最后一趟还是普通的插入排
        序。这样虽然是三重循环,但元素真正交换的次数小于简单排序。由此希
        尔排序中最重要的就是设置这种间隔,即增量序列的选择,常用的有两个排
        序效率较高的增量序列:Hibbard序列和Sedgewick序列。
*/
/*
    Hibbard序列:
        (1 << (++k)) - 1 
*/
vector<int> hibbardSequence(int n)
{
    vector<int> seq;
    int temp = 1, k = 1;
    while(temp < n && temp > 0)
    {
        seq.push_back(temp);
        temp = (1 << (++k)) - 1;
    }
    return seq;
}

/*
    Sedgewick序列:
        i从1开始,j从2开始, 
        9*((1<<(i*2))-(1<<i))+1  >  (1<<(j*2))-3*(1<<j)+1 :取后者,j++ 
        9*((1<<(i*2))-(1<<i))+1  <  (1<<(j*2))-3*(1<<j)+1 :取前者,i++ 
*/ 
vector<int> sedgewickSequence(int n)
{
    vector<int> seq;
    int temp = 1, i = 1, j = 2, a, b;
    while(temp < n && temp > 0)
    {
        seq.push_back(temp);
        a = 9 * ((1 << (i * 2)) - (1 << i)) + 1;
        b = (1 << (j * 2)) - 3 * (1 << j) + 1;
        a < b ? temp = a : temp = b;
        a < b ? i++ : j++;
    }
    return seq;
}
void shellSort(int *arr, int len, vector<int> (*getSeq)(int))
{
    vector<int> seq = getSeq(len);
    int n = seq.size(), begin, temp, j, d;
    for(int i = n - 1; i >= 0; i--)     //增量序列 
    {
        d = seq[i];         //增量 
        for(begin = d; begin < len; begin++)    //插入排序 
        {
            temp = arr[begin];
            for(j = begin - d; j >= 0 && arr[j] > temp; j -= d)
                arr[j + d] = arr[j];
            arr[j + d] = temp;
        }
    }
}

int main()
{
    int arr[10];
    srand((unsigned)time(NULL));
    for(int i = 0; i < 10; i++)
        arr[i] = rand() % 10;
    for(int i = 0; i < 10; i++)
        cout << arr[i] << " ";
    cout << endl;
    shellSort(arr, 10, sedgewickSequence);
    for(int i = 0; i < 10; i++)
        cout << arr[i] << " ";
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值