新手讲排序:归并排序
归并排序给我的感觉:编程一定要认真,不然就算你能想通也要纠缠你很长时间
(1)本质:
1.分解:用二分法,每次将数组分成两个元素数量相同或者差一个(奇数)的子数组,然后递归直到将子数组分成一个一个的元素,实际数组不用分,你直接将它看成已经分好的元素
2.合并:将len=1的数组合并成len=2的数组,合并的时候通过将两个数组的元素按大小插入到临时数组,再将临时数组元素赋予原数组,所以我们得到从len=1到len=len/2的每一个数组都是有序的
(2)例子: 10个元素的例子
1. 10,8,9,2,5,4,6,3,7,1(直接看成拆分之后的数据)
2.第一次合并 8,10 2,9 4,5 3,6 1,7
3.第二次合并 2,8,9,10 3,4,5,6 1,7
4.第四次合并 2,3,4,5,6,8,9,10 1,7
5.第五次合并 1,2,3,4,5,6,7,8,9,10
(3)代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 using namespace std; 3 //这个逻辑比较简单,两个数组都有序,通过将他们插入到临时数组来合并 4 void merge(int *a,int low,int mid,int high){ 5 int i=low,j=mid+1,num=0; 6 int temp[high-low+1]; 7 memset(temp,0,sizeof(temp)); 8 while(i<=mid&&j<=high){ 9 if(a[i]<=a[j]) temp[num++]=a[i++]; 10 else temp[num++]=a[j++]; 11 } 12 while(i<=mid) temp[num++]=a[i++]; 13 while(j<=high) temp[num++]=a[j++]; 14 for(i=0;i<high-low+1;i++){ 15 a[i+low]=temp[i]; 16 } 17 18 } 19 void merge_pass(int *a,int gap,int length){ 20 int i=0; 21 //合并长度为gap的两个区间 22 for(i=0;i+2*gap-1<length;i+=2*gap){ 23 merge(a,i,i+gap-1,i+2*gap-1); 24 } 25 //此时i+2*gap-1>length;此时的i-1<length ,则此时 剩下的两个区间i,i+gap-1,length-1 26 //如果此时i+gap-1>=length ,说明此时最后剩一个区间了,那显然不用与任何其他区间合并 27 if(i+gap-1<length-1){ 28 merge(a,i,i+gap-1,length-1); 29 } 30 } 31 //上面是合并两个区间的,这里利用循环,将它最终合并成一个区间 32 void merge_sort(int *a,int length){ 33 for(int gap=1;gap<length;gap=2*gap) 34 merge_pass(a,gap,length); 35 } 36 int main(){ 37 int a[20]; 38 int N,m,i,j; 39 cin>>N; 40 for(i=0;i<N;i++){ 41 cin>>a[i]; 42 } 43 merge_sort(a,N); 44 for(i=0;i<N;i++) 45 cout<<a[i]<<" "; 46 cout<<endl; 47 return 0; 48 }