折半、二路插入排序

折半插入排序:直接插入排序是将待插入元素与前面的元素一一比较,寻找合适的位置插入。而折半插入是通过折半来查找位置,所谓折半(可以参考二分查找)就是定义两个变量分别指向头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 }

 

 

 

 

 

 

posted @ 2019-12-12 21:42  捞的不谈  阅读(1598)  评论(0编辑  收藏  举报