归并排序思想及实现
-
主要思想
归并排序主要使用的是分治的思想,但其操作的重点并不在于分治,而在于归并。
所以接下来我们先了解一下归并这个操作,当熟练掌握归并的操作以后,归并排序也就很好掌握。
-
归并
如果我们现在分别有两个有序的序列
1,4,6,7,9
2,5,8,10,12,15
我们对这两个有序序列进行归并的操作即:将这两个有序序列合并成一个有序序列
接下来介绍完成归并的一般步骤
-
设置位置指针
我们暂且称上述两个序列为
A
序列和B
序列,我们定义两个指针Pointa
和Pointb
来指向这两个序列的头部元素例如
Pointa
指向A
序列的头部元素1
同理
Pointb
指向B
序列的头部元素2
-
移动指针进行比较来完成合并
我们需要再定义一个序列
C
来存放A
和B
合并的结果-
在两个指针的当前位置进行比较
比如初始时,
Pointa
指向1
,且Pointb
指向2
,此时明显1<2
所以先将Pointa
指针指向的元素值放入C
中,并将Pointa
指针移到下一位,也就是4
接下来同样比较两个指针所指向的数值,又因为
2<4
所以我们将Pointb
指向的元素放入C
中,并将指针后移一位 -
直到一个序列已经完全放入
C
中这时将另一个还有剩余的序列剩下的元素直接放入
C
中即可
-
程序代码:
vector<int> Merge(vector<int>& a,vector<int>& b){ vector<int> ans; //保存答案 //定义指向两个序列的指针 int Pointa=0; int Pointb=0; while(Pointa<a.size()&&Pointb<b.size()){ //比较两个序列当前指针所指元素 并选择将谁放入答案序列中 if(a[Pointa]<=b[Pointb]){ ans.push_back(a[Pointa]); Pointa++; } else{ ans.push_back(b[Pointb]); Pointb++; } } //找出仍有剩余的序列 并将其剩余元素全部放入答案序列中 while(Pointa<a.size()) ans.push_back(a[Pointa++]); while(Pointb<b.size()) ans.push_back(b[Pointb++]); return ans; }
-
-
分治
在我们理解了归并的操作以后,就可以利用分治的思想来对无序数组进行排序
这里我们利用二分法将无序序列分解到单个元素时,这些单个元素就可以视作一个有序的序列,接下来我们只需要一步一步的把这个序列进行上述的归并操作来合并成长的有序序列,再返回上去,就可以得到完整有序的序列,具体操作如下:
每一次进行一个Merge
操作,最终得到有序序列
程序代码:
vector<int> Sort(vector<int>& a,int lo,int hi){
//这里的lo和hi分别代表当前序列的最低下标和最高下标
vector<int> ans;
//用来记录答案
if(lo==hi){
//当分解到单个数的时候 默认已经有序 返回该序列
ans.push_back(a[lo]);
return ans;
}
int mid=(lo+hi)>>1; //计算出中间值
//通过递归的方式将左右两边排好序
vector<int> left=Sort(a,lo,mid);
vector<int> right=Sort(a,mid+1,hi);
//整合左右两侧的有序序列成一个有序序列并返回
return Merge(left,right);
}
至此,归并排序大体完成
-
总代码
#include<iostream> #include<vector> using namespace std; vector<int> Merge(vector<int>& a,vector<int>& b){ vector<int> ans; //保存答案 int Pointa=0; int Pointb=0; while(Pointa<a.size()&&Pointb<b.size()){ if(a[Pointa]<=b[Pointb]){ ans.push_back(a[Pointa]); Pointa++; } else{ ans.push_back(b[Pointb]); Pointb++; } } while(Pointa<a.size()) ans.push_back(a[Pointa++]); while(Pointb<b.size()) ans.push_back(b[Pointb++]); return ans; } vector<int> Sort(vector<int>& a,int lo,int hi){ vector<int> ans; if(lo==hi){ ans.push_back(a[lo]); return ans; } int mid=(lo+hi)>>1; vector<int> left=Sort(a,lo,mid); vector<int> right=Sort(a,mid+1,hi); return Merge(left,right); } int main(){ vector<int> a; int n,x; cin>>n; for(int i=1;i<=n;i++){ cin>>x; a.push_back(x); } vector<int> ans=Sort(a,0,a.size()-1); for(int i=0;i<ans.size();i++) cout<<ans[i]<<" "; cout<<endl; }