归并排序思路
将数组划分成左右俩边,使的左右俩边的数组都是有序的,然后在合并俩边数组。
归并排序步骤
第一步 以mid为中点递归划分区间,直到不能划分(即区间只有一个数)
第二步 左右俩区间合并排序 排序的数储存到临时数组中
第三步 将排好序的临时数组复制给要排序的原数组
图示
第一步 以mid为中点划分区间
第二步合并区间 根据递归返回的顺序合并区间
6 和 8 合并排序 1 和 5 合并排序 4和2 合并排序 3 和 7 合并排序
数组 6 8 和数组 1 5 合并排序 数组2 4 和数组 3 7 合并排序
数组 1 5 6 8 和 数组 2 3 4 7 排序
如何实现排序的
从上图示中可以看出归并排序,要归并排序的俩数组都是有序的,然后归并时可以使用俩个标记 i,j 分别指向俩数组的开头位置,比较俩数组 ,储存到一个临时数组。
如果i指向的数小于等于j指向的数就把i指向的数存到临时数组中同时i++
否则把j指向的数存到临时数组中同时j++。
当俩数组其中一个数组已经遍历到了最后,就把另一个数组剩余的数存到临时数组中。详见代码区间合并
实现代码
#include<iostream>
using namespace std;
const int N = 100010;
int a[N],tmp[N];
void merge_sort(int a[],int l,int r)
{
// 递归的出口 当数组只有一个元素时 不在划分区间
if(l == r) return ;
//1 递归划分区间 以 mid 为中点 划分左右区间 直到区间只有一个数
int mid = l + r >>1;
merge_sort(a,l,mid),merge_sort(a,mid + 1, r);
//2 区间合并
int i =l, j = mid +1, k = 0; // 俩区间合并 i,j 分别指向俩区间的开头 tmp[k]临时储存俩区间合并的数组
while(i <= mid && j <= r) // i , j 分别从俩区间的开头移动
{
if(a[i] <= a[j]) tmp[k++] = a[i++]; // i 下标的数组 小于等于 j 下标的数组 tmp[k]储存 i,k向后移动
else tmp[k++] = a[j++]; // 否则 就tmp[k] 储存a[j]的值 j,k 向后移动
} // 当俩区间有一个区间排序完后 跳出循环
while(i <= mid) tmp[k++] = a[i++]; // 第二区间完成排序 ,第一个区间还留有数组 tmp[]储存剩余数组
while(j <= r) tmp[k++] = a[j++]; // 第一区间完成排序 ,第二个区间还留有数组 tmp[]储存剩余数组
//4 将排好序的数组(临时数组) 复制给要排序的原数组
for(int i = l, j=0;i <= r; i ++, j ++)
a[i] = tmp[j];
}
int main()
{
int n;
cin>>n;
for(int i = 0; i <n;i ++) cin>>a[i];
merge_sort(a,0,n-1);
for(int i = 0;i <n;i ++) cout<<a[i]<<' ';
return 0;
}