【筆記】2-路插入排序

Time-space發表於2017-11-03

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

  2-路插入排序是在折半插入排序的基礎上再改進,其目的是減少排序過程中移動記錄的次數,但為此需要n個記錄的輔助空間。

  基本演算法思想:另設一個與L.r同型別的陣列d,首先將L.r[1]賦值給d[1],並將d[1]看成是在排好序的序列中處於中間位置的記錄,然後從L.r中的第2個記錄起依次插入到d[1]之前或之後的有序序列中。先將待插記錄的關鍵字和d[1]的關鍵字進行比較,若L.r[i].key<d[1].key

L.r[i].key<d[1].key
,則將L.r[i]插入到d[1]之前的有序表中;反之,則將L.r[i]插入到d[1]之後的有序表中。在實現演算法時,可將d看成是一個迴圈向量,並設兩個指標first和final分別指示排序過程中得到的有序序列中的第一個記錄和最後一個記錄在d中的位置。


這裡寫圖片描述

  在2-路插入排序中,移動記錄的次數約為n2/8

n^2/8
。因此,2-路插入排序只能減少移動記錄的次數,而不能絕對避免移動記錄。並且,當L.data[1]是帶排序記錄中關鍵字最小或最大的記錄時,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; /* 順序表型別 */
  • 2-路插入排序函式
void P2_InsertSort(SqList *L)
 { /* 2_路插入排序 */
   int i,j,first,final;
   RedType *d;
   d=(RedType*)malloc((*L).length*sizeof(RedType)); /* 生成L.length個記錄的臨時空間 */
   d[0]=(*L).r[1]; /* 設L的第1個記錄為d中排好序的記錄(在位置[0]) */
   first=final=0; /* first、final分別指示d中排好序的記錄的第1個和最後1個記錄的位置 */
   for(i=2;i<=(*L).length;++i)
   { /* 依次將L的第2個~最後1個記錄插入d中 */
     if ((*L).r[i].key<d[first].key)
     { /* 待插記錄小於d中最小值,插到d[first]之前(不需移動d陣列的元素) */
       first=(first-1+(*L).length)%(*L).length; /* 設d為迴圈向量 */
       d[first]=(*L).r[i];
     }
     else if((*L).r[i].key>d[final].key)
     { /* 待插記錄大於d中最大值,插到d[final]之後(不需移動d陣列的元素) */
       final=final+1;
       d[final]=(*L).r[i];
     }
     else
     { /* 待插記錄大於d中最小值,小於d中最大值,插到d的中間(需要移動d陣列的元素) */
       j=final++; /* 移動d的尾部元素以便按序插入記錄 */
       while((*L).r[i].key<d[j].key)
       {
         d[(j+1)%(*L).length]=d[j];
         j=(j-1+(*L).length)%(*L).length;
       }
       d[j+1]=(*L).r[i];
     }
   }
   for(i=1;i<=(*L).length;i++) /* 把d賦給L.r */
     (*L).r[i]=d[(i+first-1)%(*L).length]; /* 線性關係 */
 }
  • 主程式
 #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賦值 */
     l.r[i+1]=d[i];
   l.length=N;
   printf("排序前:\n");
   print(l);
   P2_InsertSort(&l);
   printf("2_路插入排序後:\n");
   print(l);
 }

相關文章