1. 程式人生 > 其它 >資料結構之直接插入排序和希爾排序

資料結構之直接插入排序和希爾排序

資料結構中有很多排序演算法,以下講解直接插入排序和希爾排序,剩下的排序演算法以後會更新。

1, 直接插入排序

(1)直接插入排序概念:從陣列頭一個一個元素開始排序,此時第i個元素之前都是從小到大排序好的,將第i個元素插入到前i個元素中去就好,以此類推,直到將n個元素全部插入完成。直接插入排序相關演算法如下

 1 void InsertSort(int A[],int n)
 2 {
 3     int i,j,temp;
 4      for(i=1;i<n;i++)         //將各個元素插入到已排好序的序列中
 5        {
 6             if
(A[i]<A[i-1]) //若A[j]元素小於前驅 7 { 8 temp=A[i]; //用temp儲存A[i] 9 for(j=i-1;j>=0&&A[j]>temp;j--) //檢查所有已排好序的元素 10 A[j+1]=A[j]; //大於temp的元素都向後挪位 11 A[j+1]=temp;//將要插入的元素插入到序列中 12 } 13 }
14 } 15

2,分析演算法效率

(1) 空間效率:僅使用了常數個輔助單元,因而空間複雜度為O(1);

(2)時間效率:在最好的情況下,表中元素已經有序,此時每插入一個元素,都只需要比較一次而不用移動元素,因而時間複雜度為O(n).

在最壞情況下:表中元素順序剛好與排序結果中的元素順序相反(逆序)總的比較次數為:(n+2)(n-1)/2, 總的移動次數為:∑i=2n(i+1)。

因此,直接插入排序演算法的時間複雜度為O(n2)。

(3)穩定性:直接插入排序是一個穩定的排序演算法。

2,折半插入排序

(1)折半插入排序是直接插入排序的改進型,由於是順序儲存的線性表,所以查詢有序子表時可以用折半查詢實現。

相關程式碼如下

 1 void InsertSort(int A[],int n)
 2 {
 3     int i,j,low,high,mid;
 4     for(i=2;i<=n;i++)  //依次將A[2]到A[n]插入到前面已排序的陣列中
 5     {
 6         A[0]=A[i];    //將待排序的元素存放到A[0]位置
 7         low=1;high=i-1;  //設定折半查詢範圍
 8         while(low<=high)    //折半查詢(預設遞增序列)
 9         {
10             mid=(low+high)/2;  // 取中間值
11             if(A[mid]>A[0]
12                 high=mid-1;     //插入位置在左半部分
13             else
14                  low=mid+1;     //插入位置在右半部分
15            }
16          for(j=i-1;j>=high+1;j--)//依次將大於待插入元素的值後移一位
17               A[j+1]=A[j];
18          A[high+1]=A[0];//將待插入元素插入順序表中
19      }
20 }

(2)演算法分析

從上述演算法中,不難看出折半查詢插入排序減少了比較元素的次數,約為O(nlog2n),該比較次數與待排序表的初始狀態無關,僅取決於表中的元素n。

因此,折半查詢排序的時間複雜度為O(n2)。

(3)穩定性:折半插入排序是一種穩定的排序方法。

3,希爾排序

1,希爾排序的思想:先取一個間隔d,分別取A[i],A[i+d],A[i+2d],依次往下取,分成d個子表,依次對子表進行直接插入排序,改變d的值,將d的值減小,然後按照剛才的方法進行排序,當整個表中的元素呈現”基本有序“時,再對全體記錄進行一次直接插入排序。

程式碼如下

 1 void ShellSort(int A[],int n)
 2 {
 3     for(d=n/2;d>=1;d=d/2)  //d的變化範圍
 4     {
 5           for(i=d+1;i<=n;++i)
 6            {
 7                if(A[i]<A[i-d]   //需將A[i]插入有序遞增子表
 8                {
 9                     A[0]=A[i];   //將待插入元素暫存到A[0]
10                     for(j=i-d;j>0&&A[0]<A[j];j-=d)
11                        A[j+d]=A[j];   // 記錄後移,查詢插入位置
12                    A[j+d]=A[0];  //插入
13                }
14             }
15        }
16 }

(2)空間效率:僅使用了常數個輔助單元,因此空間複雜度為O(1);

(3)時間複雜度:當n在某個特定範圍內時,希爾排序的時間複雜度約為O(n1.3).,在最壞的情況下,時間複雜度為O(n2)。

(4)穩定性:不是一種穩定的排序演算法。

(5)適用性:希爾排序演算法僅適用於線性表為順序儲存的情況。