1.2 插入排序算法之希尔排序

1、希尔排序:(Shell`s Sort)


思想:

  • 将待排序的表分成若干组
  • 每组内进行直接插排,使整个序列基本有序
  • 然后再对整个表进行更加细化的分组直接插排,始之基本有序
  • 直至无法细化分组最终有序

分组方法:

  • 对给定的一个步长d(d>0),将下标相差为d的倍数的元素分在一组。
  • 希尔排序算法经典的d的取值依次为:
    d1=n/2, d2=d1/2, ……,dk=1
    (直至步长为1,不可再分组,其中n为表长,)

—— 即不同步长进行分组,各个分组内进行”直接插入排序”,直至不能再分



语言很苍白,用图例来解决
例:数组Arr[] = {100, 8, 20, 16, 14, 7, 105,50, 78, 9}
这里写图片描述

  • Step1 : 步长d1为5,相同颜色的为一组,比如第一组为”100 & 7”,每个组进行直接插排,局部有序
  • Step2 : 第一轮结束,取步长为d2 = d1/2 , Arr[0] , Arr[2], Arr[4],Arr[6],Arr[7]相同颜色为一组;每组进行直接插排,局部有序
  • Step3 : 取步长为 d3 = d2 /2 ,为1,无法再分,对整个数组进行直接插排,整体有序

    [注] 当步长 dk=1时,其实就是对最后局部有序的数组进行直接插入排序。



希尔排序算法及分析

  • 稳定性:不稳定排序
  • 空间性能:1个辅助空间。
  • 时间性能: 与数据表初始状态关系不大:
    需要循环log2n趟,每趟O(n)
    因而时间复杂度为O(nlog2n)


代码:

#include <iostream>
using namespace std;

void Shell_sort(int *pArr, int len)
{
    int d = len / 2;

    while(d > 0)
    {
        for(int k = 0; k < d; k++)   // k : 每一个步长对应的分组数,依次对每个分组操作 
        {
            //对每一组进行 Straight_insert_Sort
            for(int i = d + k; i<len; i=i+d)
            {
                int temp = pArr[i];

                int j = i - d;

                while( j >= 0 && (pArr[j] > temp))
                {
                    pArr[j+d] = pArr[j];

                    j-=d;
                }
                pArr[j+d] = temp;
            }

        }
        d = d / 2;
    }

    return;
}

/*
Shell_sort2 的代码实现与上图中的示例图分析理解上可能有差别,但是实现的结果是相同的;
Shell_sort 是先根据步长将组分好,然后将第一个组中进行直接插排,再将第二个组进行直接插排,依次类推.
Shell_sort2 是:
组1的第二个元素与组1第一个元素直接插排,组2的第二个元素与组2第一个元素直接插排...组k的第二个元素与组k第一个元素直接插排;
组1的第三个元素与组1前两个元素直接插排,组2的第三个元素与组2前两个元素直接插排...组k的第二个元素与组k的前两个元素直接插排
依次类推,可以看出并没有严格先将某一组按照直接插排排好,再进行下一组的整体直接插排!!!
单步一下你就知道。2代码更简洁
*/
void Shell_sort2(int *pArr, int len)
{
    int d = len / 2;

    while(d>0)
    {
        for(int i = d; i < len; i++)     //单步走一下就很清楚 
        {
            int temp = pArr[i];

            int j = i-d;

            while(j>=0 && (pArr[j] > temp))
            {
                pArr[j+d] = pArr[j];

                j = j-d;
            }

            pArr[j+d] = temp;
        }    //对给定的d,在每一组内插入排序

        d = d/2;
    }
    return;
}

int main()
{
    int a[]={100,8,20,16,14,7,105,50,78,9};
    int len = 10; 

    Shell_sort(a, len);

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

    return 0;
 } 

最后的大白话:
Shell Sort 根据步长 d(分组)进行直接插入排序。

猜你喜欢

转载自blog.csdn.net/zxj820/article/details/80413922
今日推荐