1. 程式人生 > >資料結構之直接插入排序、折半插入排序、希爾排序演算法

資料結構之直接插入排序、折半插入排序、希爾排序演算法

哪個成功的人不是一路坎坷過來的,只有這樣你才知道珍惜,知道成功的不易。有時候太容易得到的東西反而不知道珍惜。

直接插入排序:

我們的記錄本身就是基本有序的,我們只需要少量的插入操作,就可以完成整個記錄集的排序工作,此時直接插入很高效。還有就是記錄數比較少時,直接插入的優勢也比較明顯。

void InsertSort(int b[],int n)        //直接插入排序
{
    int i,j,t;
    for(i=0; i<n; i++)
    {
        t=b[i+1];
        j=i;
        while(j>=0&&t<b[j])
        {
            b[j+1]=b[j];
            j--;
        }
        b[j+1]=t;
    }
}

折半插入排序

演算法的流程就是:比如此時順序為5,3,2,4,1。分別對應陣列的a[0]...a[4]

那麼當我們進入第一次插入演算法時,low=0high=0;所以mid=0;此處用a[mid]a[0]與我們所要插入的數a[1]3進行比較。有a[mid]>3所以此時。我們就要在mid的左邊即lowmid之間進行比較了,但是mid又如何更新呢,就是要把high1;然後再求mid就可以了,這時的新的mid就在low與原來的mid之間了。然後我們再次進行比較,但是此時因為high已經小於1了,所以迴圈終止,故將原有的資料後移一位,再將要插入的元素插入low處即可。

void BinInsertSort(int b[],int n)
{
    int i,j,t,mid,low,high;
    for(i=0; i<n; i++)
    {
        t=b[i+1];
        low=0;
        high=i;
        while(low<=high)
        {
            mid=(low+high)/2;
            if(b[mid]>t)
                high=mid-1;    //在小於中間值的那部分尋找
            else
                low=mid+1;    //在大於中間值的那部分尋找
        }
        for(j=i; j>=low; j--)
        {
            b[j+1]=b[j];       //整體陣列後移
        }
        b[low]=t;
}
}

希爾排序:

希爾排序是基於插入排序的以下兩點性質而提出改進方法的:

1、插入排序在對幾乎已經排好序的資料操作時,效率高,即可以達到線性排序的效率。/

2、但插入排序一般來說是低效的,因為插入排序每次只能將資料移動一位。

希爾排序不需要大量的輔助空間,和歸併排序一樣容易實現。希爾排序是基於插入排序的一種演算法, 在此演算法基礎之上增加了一個新的特性,提高了效率。希爾排序的時間複雜度與增量序列的選取有關,例如希爾增量時間複雜度為O(n²),希爾排序時間複雜度的下界是n*log2n。希爾排序沒有快速排序演算法快 O(n(logn)),因此中等大小規模表現良好,對規模非常大的資料排序不是最優選擇。比O( n

²)複雜度的演算法快得多。並且希爾排序非常容易實現,演算法程式碼短而簡單。 此外,希爾演算法在最壞的情況下和平均情況下執行效率相差不是很多,與此同時快速排序在最壞的情況下執行的效率會非常差。希爾排序演算法的發明,使得我們終於突破了慢速排序的時代(超越了時間複雜度為O(n2)),之後,相應的更為高效的排序演算法也就相繼出現了。

希爾排序的思想就是,每隔一定增量的兩個數進行比較排序,然後得到一個得到一個基本有序的序列。這其實就是希爾排序的精華所在,它將關鍵字較小的記錄,不是一步一步地往前挪動,而是跳躍式地往前移,從而使得每次完成一輪迴圈後,整個序列就朝著有序堅實地邁進一步。

void ShellSort(int b[],int n)
{
    int i,j,t;
    int increment=n;
    do
    {
        increment=increment/3+1;          // 增量序列 
        for(i=increment; i<=n; i++)
        {
            if (b[i]<b[i-increment])      //需將b[i]插入有序增量子表 
            {
                t=b[i];                    // 暫存在t
                for(j=i-increment; j>=0 && t<b[j]; j-=increment)
                    b[j+increment]=b[j];  // 記錄後移,查詢插入位置 
                b[j+increment]=t;         //插入 
            }
        }
    }
    while(increment>1);
}

測試程式如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void InsertSort(int a[],int n)        //直接插入排序
{
    int i,j,t;
    int b[n];
    memcpy(b, a, n * sizeof(int));
    for(i=0; i<n; i++)
    {
        t=b[i+1];
        j=i;
        while(j>=0&&t<b[j])
        {
            b[j+1]=b[j];
            j--;
        }
        b[j+1]=t;
    }
    for(i=0; i<n; i++)
        printf("%4d",b[i]);
}
void BinInsertSort(int a[],int n)
{
    int i,j,t,mid,low,high;
    int b[n];
    memcpy(b,a,n*sizeof(int));
    for(i=0; i<n; i++)
    {
        t=b[i+1];
        low=0;
        high=i;
        while(low<=high)
        {
            mid=(low+high)/2;
            if(b[mid]>t)
                high=mid-1;    //在小於中間值的那部分尋找
            else
                low=mid+1;    //在大於中間值的那部分尋找
        }
        for(j=i; j>=low; j--)
        {
            b[j+1]=b[j];       //整體陣列後移
        }
        b[low]=t;
    }
    for(i=0; i<n; i++)
        printf("%4d",b[i]);
}
void ShellSort(int a[],int n)
{
    int i,j,t;
    int b[n];
    memcpy(b,a,n*sizeof(int));
    int increment=n;
    do
    {
        increment=increment/3+1;          // 增量序列 
        for(i=increment; i<=n; i++)
        {
            if (b[i]<b[i-increment])      //需將b[i]插入有序增量子表 
            {
                t=b[i];                    // 暫存在t
                for(j=i-increment; j>=0 && t<b[j]; j-=increment)
                    b[j+increment]=b[j];  // 記錄後移,查詢插入位置 
                b[j+increment]=t;         //插入 
            }
        }
    }
    while(increment>1);
    for(i=0; i<n; i++)
        printf("%4d",b[i]);
}
int main()
{
    int i;
    int p[5]= {5,3,2,4,1};
    printf("原序:");
    for(i=0; i<5; i++)
        printf("%4d",p[i]);
    printf("\n直接插入排序:");
    InsertSort(p,5);
    printf("\n折半插入排序:");
    BinInsertSort(p,5);
    printf("\n希爾排序:");
    ShellSort(p,5);
    return 0;
}

結果: