希爾排序

轉自:https://www.cnblogs.com/ronnydm/p/5905715.html

希爾排序(Shell Sort)也是插入排序的一種。也稱爲縮小增量排序,是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。該方法因DL.Shell於1959年提出而得名。

基本思想:
  將待排序列劃分爲若干組,在每一組內進行插入排序,以使整個序列基本有序,然後再對整個序列進行插入排。

在這裏插入圖片描述  在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
再從百度上貼個示例:
在這裏插入圖片描述
在這裏插入圖片描述

希爾增量:
  希爾增量是指希爾提出了一種衝破二次時間屏障的算法。
  Donald Shell 提出了一種衝破二次時間屏障的算法Shellsort(希爾排序),在希爾排序中希爾給出了一組增量序列:ht = N / 2, h[k] = h[k+1] / 2,即 {N/2, (N / 2)/2, …, 1},這個序列就叫做希爾增量。這個是編寫希爾排序時最常用的序列,但卻不是最好的。其餘的增量序列還有Hibbard:{1, 3, …, 2^k-1},Sedgewick:{1, 5, 19, 41, 109…}該序列中的項或者是94^i - 92^i + 1或者是4^i - 3*2^i + 1。使用不同的增量對希爾排序的時間複雜度的改進將不一樣,甚至一點小的改變都將引起算法性能劇烈的改變。

優劣:
  1. 不需要大量的輔助空間,和歸併排序一樣容易實現。
  2. 希爾排序的時間複雜度與增量序列的選取有關,例如希爾增量時間複雜度爲O(n²),而Hibbard增量的希爾排序的時間複雜度爲O(),希爾排序時間複雜度的下界是n*log2n。
  3. 希爾排序沒有快速排序算法快 O(n(logn)),因此中等大小規模表現良好,對規模非常大的數據排序不是最優選擇。
  4. 希爾算法在最壞的情況下和平均情況下執行效率相差不是很多,而快速排序在最壞的情況下執行的效率會非常差。
代碼 :

#include <stdio.h>

void println(int array[], int len)
{
    int i = 0;
    for(i=0; i<len; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
}

void swap(int array[], int i, int j)
{
    int temp = array[i];    
    array[i] = array[j];
    array[j] = temp;
}

void ShellSort(int array[], int len) // O(n*n)
{
    int i = 0;
    int j = 0;
    int k = -1;
    int temp = -1;
    int gap = len;
    do {
        gap = gap / 3 + 1;
        for (i=gap; i<len; i+=gap) {
            k = i;
            temp = array[k];
            for (j=i-gap; (j>=0) && (array[j]>temp); j-=gap) {
                array[j+gap] = array[j];
                k = j;
            }
            array[k] = temp;
        }
    } while (gap > 1);
}

int main()
{
    int array[] = {21, 25, 49, 25, 16, 8};
    int len = sizeof(array) / sizeof(*array); 

    println(array, len);

    ShellSort(array, len);

    println(array, len);

    return 0;
}



#include<stdio.h>
#include<math.h>
 
#define MAXNUM 10
 
void main()
{
    void shellSort(int array[],int n,int t);//t爲排序趟數
    int array[MAXNUM], i;
    for (i=0; i<MAXNUM; i++)
        scanf("%d",&array[i]);
    shellSort(array, MAXNUM, int(log(MAXNUM+1)/log(2)));//排序趟數應爲log2(n+1)的整數部分
    for(i=0;i<MAXNUM;i++)
        printf("%d ",array[i]);
    printf("\n");
}
 
//根據當前增量進行插入排序
void shellInsert(int array[],int n,int dk)
{
    int i,j,temp;
    for (i=dk; i<n; i++) { //分別向每組的有序區域插入
        temp = array[i];
        for(j=i-dk; (j>=i%dk) && array[j]>temp ;j-=dk)//比較與記錄後移同時進行
            array[j+dk]=array[j];
        if(j!=i-dk)
            array[j+dk]=temp;//插入
    }
}
 
//計算Hibbard增量
int dkHibbard(int t,int k)
{
    return int(pow(2,t-k+1)-1);
}
 
//希爾排序
void shellSort(int array[],int n,int t)
{
    void shellInsert(int array[],int n,int dk);
    int i;
    for(i=1;i<=t;i++)
        shellInsert(array,n,dkHibbard(t,i));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章