【筆記】折半插入排序

Time-space發表於2017-11-03

  插入排序的演算法思想:將待排序元素分為已排序子集和未排序子集,一次從未排序子集中的一個元素插入已排序子集中,使已排序自己仍然有序;重複執行以上過程,指導所有元素都有序為止。

  折半插入排序:演算法是直接插入排序的改進。它的主要改進在於在已經有序的集合中使用折半查詢法確定待排序元素的插入位置, 找到要插入的位置後,將待排序元素插入相應的位置。

  假設待排序的元素有7個,分別為67、53、73、21、34、98、12。使用折半插入排序對該元素序列第一堂排序的過程如下圖所示。


這裡寫圖片描述

  第2趟折半插入排序過程如下圖所示。


這裡寫圖片描述

  從以上兩趟排序過程可以看出,折半插入排序與直接插入排序的區別僅僅在於查詢插入的位置的方法不同。一般情況下,折半查詢的效率要高於順序查詢的效率,因此折半插入排序演算法可以減少比較的次數。
  通過對直接插入排序演算法的簡單修改,得到如下折半插入排序的演算法:

  • 型別定義標頭檔案
 #define MAXSIZE 20 /* 一個用作示例的小順序表的最大長度 */
 typedef int InfoType; /* 定義其它資料項的型別 */
 typedef int KeyType; /* 定義關鍵字型別為整型 */
 typedef struct
 {
   KeyType key; /* 關鍵字項 */
   InfoType otherinfo; /* 其它資料項,具體型別在主程中定義 */
 }RedType; /* 記錄型別 */

 typedef struct
 {
   RedType r[MAXSIZE+1]; /* r[0]閒置或用作哨兵單元 */
   int length; /* 順序表長度 */
 }SqList; /* 順序表型別 */
  • 函式檔案
void BinInsertSort(SqList *L)
/*折半插入排序*/
{
    int i,j,mid,low,high;
    DataType t;
    for(i=1;i<L->length;i++)        /*前i個元素已經有序,從第i+1個元素開始與前i個的有序的關鍵字比較*/
    {
        t=L->data[i+1];             /*取出第i+1個元素,即待排序的元素*/
        low=1,high=i;
        while(low<=high)            /*利用折半查詢思想尋找當前元素的合適位置*/
        {
            mid=(low+high)/2;
            if(L->data[mid].key>t.key)
                high=mid-1;
            else
                low=mid+1;
        }
        for(j=i;j>=low;j--)     /*移動元素,空出要插入的位置*/
            L->data[j+1]=L->data[j];
        L->data[low]=t;         /*將當前元素插入合適的位置*/    
    }
}
  • 主程式
 #define LT(a,b) ((a)<(b))
 #define N 8
 void print(SqList L)
 {
   int i;
   for(i=1;i<=L.length;i++)
     printf("(%d,%d)",L.r[i].key,L.r[i].otherinfo);
   printf("\n");
 }

 void main()
 {
   RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}};
   SqList l;
   int i;
   for(i=0;i<N;i++) /* 給l1.r賦值 */
     l1.r[i+1]=d[i];
   l.length=N;
   printf("排序前:\n");
   print(l);
   BInsertSort(&l);
   printf("折半插入排序後:\n");
   print(l);
 }

相關文章