排序——希爾排序法

1、希爾排序法的概念算法

希爾排序又稱爲縮小增量排序,該排序方法也屬於插入排序類的算法,是對直接插入排序的一種改進。測試

2、算法描述code

    對於直接插入排序法,若是數據原來就已經按要求的順序排列,則在排序過程當中不須要進行數據移動操做,便可獲得有序數列。可是,若是最初的數據是按倒序排列的,則在進行插入排序時每次的比較都須要向後移動數據,這樣,將致使算法的效率很低。
    也就是說,若是在進行直接插入排序時,數據已是基本有序的,則排序的效率就可大大提升。另外,對於數量較小的序列使用直接插入排序,因須要移動的數據量較少,其效率也較高。
    針對這兩個特色,對直接插入排序進行改進,就獲得了希爾排序算法。
    希爾排序的基本思想就是:將須要排序的序列劃分爲若干個較小的序列,對這些序列進行直接插入排序,經過這樣的操做可以使須要排序的數列基本有序,最後再使用一次直接插入排序對整個數列進行排序。這樣,首先對數量較小的序列進行直接插入排序可提升效率,最後對基本有序的序列進行直接插入排序,也可提升效率,從而使整個排序過程的效率獲得提高。排序

注意:在希爾排序中首先要解決的是怎樣劃分子序列。對於子序列的構成不是簡單地分段,而是採起將相隔某個增量的數據組成一個序列。通常選擇增量的規則是:取上一個增量的一半做爲這次子序列劃分的增量,通常初始值取元素的總數量。io


例如,有10個數據,可以使增量爲5,則序號一、5爲一個子序列,二、6爲一個子序列……對這些子序列排序後,再縮小增量,從新劃分子序列進行排序,直到增量爲1時結束排序過程。
下面以一組待排序的數據演示希爾排序的過程,假設有8個須要排序的數據序列以下:
69,65,90,37,92,6,28,54
使用希爾排序法進行排序的過程如下圖1所示,具體排序過程以下:
(1)首先使用元素總數量的一半(值爲4)做爲增量,將數據劃分爲4個子序列。對這4個序列分別進行排序,其中第二、6和第三、7子序列須要進行數據交換。交換後獲得第1遍排序的結果。
(2)接着將增長縮小一半(值爲2)從新劃分子序列,獲得兩個子序列。對這兩個子序列分別進行排序,獲得第2遍排序後的結果。
(3)再次縮小增量(值爲1),此時全部數據構成1個序列,對該序列使用直接插入排序,獲得最後排序結果。在下圖1所示的排序過程當中,第1遍排序進行了兩次數據交換(65與6交換、90與28交換),第2次排序進行了3次數據交換(69與28交換、90與92交換、65與54交換),最後一遍進行了7次數據交換(再也不列出,讀者可去分析),一共需交換數據12次。class

                    

圖1 希爾排序過程效率

    若是不使用希爾排序,而使用直接插入排序對原數據進行排序,則須要進行19次數據交換,算法的效率大大下降。
    因而可知,使用希爾排序法可顯著地減小數據交換的次數,從而提升排序的效率。
    提示:以上例子中只使用了8個數據,需排序的數據量越大,越能體現出希爾排序算法的效率。循環

3、算法實現gc

一、希爾排序方法

/**
 *希爾排序
 * */
void ShellSort(int a[], int n)
{
    int d, i, j, x;

    d = n/2; //計算第一次的增量

    while (d>=1) {//循環至增量爲1是結束
        for (i=d; i<n; i++) {
            x = a[i]; //獲取序列中的下一個數據
            j = i-d; //獲取序列中前一個數據的序號

            while (j>=0 && x < a[j]) {
            	a[j+d] = a[j];
            	j = j-d;
            }
            a[j+d] = x;
        }
        d /=2;
    }
}

二、希爾排序測試

#include <stdio.h>
#include <stdlib.h>
#include "ShellSort.c"

#define ARRAYLEN 8

void ShowData(int arr[], int n)
{
    int i;
    for (i=0; i<n; i++)
        printf("%d ", arr[i]);
    printf("\n");

    return;
}

int main(int argc, char *argv[])
{
    int i;
    int a[ARRAYLEN] = {69, 65, 90, 37, 92, 6, 28, 54};

    printf("原數據:");
    ShowData(a, ARRAYLEN);

    InsertSort(a, ARRAYLEN);
    printf("排序後:");
    ShowData(a, ARRAYLEN);
    return 0;

}

運行結果:

相關文章
相關標籤/搜索