折半插入排序:直接插入排序是將待插入元素與前面的元素一一比較,尋找合適的位置插入。而折半插入是通過折半來查找位置,所謂折半(可以參考二分查找)就是定義兩個變量分別指向頭start和尾end,取其中間值mid。如果待插入元素大於mid位置上的元素就這mid和end之間再查找,如果小於,則在start和mid之間查找。然後不斷縮小範圍,直到尋找到合適的位置(大於左邊小於右邊),然後就是元素的插入。
1 #include<stdio.h> 2 #define n 6 3 4 5 void binaryInsertSort(int num[]){ 6 7 int start,end,mid,i,j,t; 8 for(i=1;i<n;i++){ 9 start = 0; //開始位置從0開始 10 end = i-1; //結束位置在待插入元素的前一個位置 11 while(start<=end){ //循環條件 12 mid = (start+end)/2; 13 if(num[i]>=num[mid]) //如果此條件成立 14 start = mid + 1; //就說明待插入元素的插入位置應該在mid和end之間 15 else 16 end = mid - 1; //否則說明待插入元素的插入位置應該在start和mid之間 17 } 18 19 if(start>mid) //如果start>mid,說明待插入元素比mid位置的元素大,但比mid+1位置上的元素小 20 mid++; //此時插入位置應該是mid+1 21 //還有一種情況就是end<mid,說明待插入元素比mid位置的元素小 22 //此時插入位置應該是mid 23 24 t = num[i]; //此處就是元素的插入 25 for(j=i-1;j>=mid;j--) //使用直接插入排序代碼思想在此處插入元素 26 num[j+1] = num[j]; 27 num[j+1] = t; 28 29 } 30 31 }
二路插入排序:前面的插入排序每次插入元素的時候都會移動較多的元素,二路插入排序對其進行了改善。思路是:以第一個元素作爲比較元素,後面所有大於該元素的數全部放在前面,所有小於元素的數放在後面,大於或小於部分的元素在插入的時候使用直接插入排序來保證有序,當所有元素分配好後,其實數組已經變成兩個有序區,在組合好就完成排序了。
定義first、final指向兩個有序區,圖解如下:
1 #include<stdio.h> 2 #define n 6 3 4 5 void twoInsertSort(int num[]){ 6 7 int i,j,first,final,temp[n+1]={0}; //臨時存放數組比原有數組多一個空間 8 first = 0; //first、final分別指向臨時存放數組的開頭和結尾 9 final = n; 10 temp[0] = num[0]; //數組第一個元素作爲比較元素 11 12 for(i=1;i<n;i++){ 13 if(num[i]>=num[0]){ //大於第一個元素的數放在臨時數組的前面 14 j = first; //first作爲大於第一個元素的數的最後元素的下標 15 while(num[i]<=temp[j]){ //在這裏使用直接插入,使其有序 16 temp[j+1] = temp[j]; 17 j--; 18 } 19 temp[j+1] = num[i]; 20 first++; 21 } 22 else{ 23 j = final; //小於第一個元素的數放在臨時數組的後面 24 while(num[i]>temp[j]){ //在這裏使用直接插入,使其有序 25 temp[j-1] = temp[j]; 26 if((++j)>=n+1) //這裏是爲了防止數組向後越界 27 break; 28 } 29 temp[j-1] = num[i]; 30 final--; //final作爲小於第一個元素的數的最前元素的下標 31 } //但final指向了最前元素的前一個位置 32 } 33 34 for(i=0;i<n-1-first;i++) //將臨時數組存放到原來的數組 35 num[i] = temp[++final]; 36 37 for(j=0;i<n;j++,i++) 38 num[i] = temp[j]; 39 40 } 41 42 void main(){ 43 44 int i,num[n] = {890,761,812,761,810,261}; 45 twoInsertSort(num); 46 47 for(i=0;i<n;i++) 48 printf("%d ",num[i]); 49 50 }