欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

希尔排序(Shell Sort)

程序员文章站 2024-03-19 13:05:22
...
#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;
}
相关标签: DSA