归并排序是完全遵循
分治法实现的。
分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。
解决:使用归并排序
递归地排序两个子序列。
合并:合并两个已排序的子序列以产生已排序的序列。归并排序的
关键操作是“合并”步骤中两个已排序序列的合并。
下图展示归并排序的全部过程,以数组{38,27,43,3,9,82,10}为例。
![](https://i-blog.csdnimg.cn/blog_migrate/d224478b9415245d16bff528cb808302.png)
两个有序序列的合并,只要比较两个序列中的第一个数,谁小取谁。
/*把数组arr[l..m]和 arr[m+1...r]合并*/
void merge(int arr[],int l,int m,int r){
int i,j,k;
int n1 = m-l+1;
int n2 = r-m;
int L[n1], R[n2];
/*复制arr[]中的数据 */
for(i=0;i<n1;i++)
L[i] = arr[i+l] ;
for(j=0;j<=n2;j++)
R[j] = arr[j+m+1];
i=0;k=l;j=0;
/*合并*/
while(i<n1&&j<n2){
if(L[i]<=R[j])
arr[k++] = L[i++];
else
arr[k++]=R[j++];
}
while(i<n1)
arr[k++] = L[i++];
while(j<n2)
arr[k++] = R[j++];
}
具体思路:先将数组分成1,2两组,如果2组中的数据已经是有序的,则将这两个数组合并。但是如何实现有序呢?可以继续将1,2两组各自再分成两组。当只有一个数据时就是有序的,在合并相邻的两组数据即可。简单的说就是: 先递归分解, 再合并。
#include<iostream>
#include<cstdio>
using namespace std;
/*把数组arr[l..m]和 arr[m+1...r]合并*/
void merge(int arr[],int l,int m,int r){
int i,j,k;
int n1 = m-l+1;
int n2 = r-m;
int L[n1], R[n2];
/*复制arr[]中的数据 */
for(i=0;i<n1;i++)
L[i] = arr[i+l] ;
for(j=0;j<=n2;j++)
R[j] = arr[j+m+1];
i=0;k=l;j=0;
/*合并*/
while(i<n1&&j<n2){
if(L[i]<=R[j])
arr[k++] = L[i++];
else
arr[k++]=R[j++];
}
while(i<n1)
arr[k++] = L[i++];
while(j<n2)
arr[k++] = R[j++];
}
/*递归分解*/
void mergeSort(int arr[],int l,int r){
if(l<r){
int m=l+(r-l)/2;
mergeSort(arr,l,m);
mergeSort(arr,m+1,r);
merge(arr,l,m,r);
}
}
int main(){
int arr[]={38,27,43,3,9,82,10};
int arr_size=sizeof(arr)/sizeof(arr[0]);
mergeSort(arr,0,arr_size-1);
for(int i=0;i<arr_size;i++){
printf("%d%c",arr[i],(i==arr_size-1)?'\n':' ');
}
return 0;
}