C++希尔排序

纵然是瞬间 提交于 2019-12-02 06:47:37

希尔排序的提出:
直接插入排序算法的问题:
若一个最小的值在后面,那么当排这个最小值的时候需要一步步移动,将其移动到序列的最前面,那么有没有什么方法减少这种移位?
我们不希望一步一步移动,而是给它设置一个增量让其大步移动,希尔排序由此产生,同时希尔排序打破了排序算法时间复杂度不能低于O(n2)

希尔排序采用跳跃分割的策略:
将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后的得到的结果基本有序而不是局部有序。

这里简单介绍一下基本有序的概念:小的关键字基本在前面,大的基本在后面,不大不小的基本在中间,像{2,1,,3,6,4,7,5,8,9}就可以称为基本有序,{1,5,9,3,7,8,2,4,6}就不能称为基本有序,因为最大的9在第三位,并且很小的2在导数第三位。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:
1.插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
2.但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

希尔排序的基本思想:
先取小于n的整数d1作为第一个增量,把全部记录分组。所有距离为d1倍数的记录放在同一组中,先在各组内进行直接插入排序;然后,去第二个增量d2<d1重复上述的分组和排序,直到所取的增量dt=1(dt<dt1<...<d2<d1),即所有记录被放在同一组中进行直接插入排序为止。
希尔排序举例说明:
对于序列为{592,401,874,141,348,72,911,887,820,283}进行希尔排序:
假设第一步选择的增量为5,592和72一组,对改组进行插入排序,应该交换两者顺序,同理,对于其他组采用相同的操作,得到的序列为{72,401,874,141,283,592,911,887,820,348};
对于上述得到的序列,假设第二步选择的增量为2,{72,874,283,911,820}为一组,采用插入排序得到的序列为{72,283,820,874,911},同理对于另一组{401,141,592,887,820,348}采用相同的操作得到的序列为{141,348,401,592,887},最终得到的序列为{72,141,283,348,820,401,874,592,911,887};
对于上述得到的序列,第三步选择的增量为1,整个序列为一组,进行插入排序得到的序列为{72,141,283,348,401,592,820,874,887,911}。
希尔排序的代码实现:

#include<iostream>
using namespace std;

void ShowArr(int arr[], int length)
{
    if (arr == nullptr || length <= 0)
        return;
    for (int i = 0; i < length; i++)
    {
        cout << arr[i] << "\t";
    }
    cout << endl;
}

void ShellSort(int arr[], int length)
{
    if (arr == NULL || length <= 0)
        return;
    int increment = length;
    while (increment > 1)
    {
        increment = increment / 3 + 1;
        for (int i = increment; i < length; i++)
        {
            int temp = arr[i];
            if (arr[i] < arr[i - increment])
            {
                int j;
                for (j = i - increment; j >= 0 && arr[j] > temp; j = j - increment)
                    arr[j + increment] = arr[j];
                arr[j + increment] = temp;
            }
        }
    }
}

int main()
{
    int arr[] = { 592,401,874,141,348,72,91,887,820,283 };
    int length = sizeof(arr) / sizeof(int);
    ShowArr(arr, length);
    ShellSort(arr, length);
    ShowArr(arr, length);

    system("pause");
    return 0;
}

希尔排序的时间复杂度分析:
希尔排序的时间复杂度与增量的设置有关,但是应该选取什么样的增量才是最好的,目前还是一个数学难题。常用的增量序列有increment = increment / 2,简称为希尔增量,但是当使用该增量时,时间复杂度为O(n2),不是最优的,还常使用的增量为increment = increment / 3 + 1,时间复杂度为O(n3/2)。需要注意的是,增量序列的最后一个增量必须等于1才行。另外由于记录是跳跃式的移动,希尔排序并不是一种稳定的排序算法。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!