C++归并排序
归并排序是建立在归并操作基础上的一种有效的排序算法,采用分治的思想,将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表。称为二路归并,归并排序是稳定排序。
归并操作,指是将两顺序序列合并成一个顺序序列的方法。
如:设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并:{6,202}{100,301},{8,38},{1} 比较3次
第二次归并:{6,100,202,301},{1,8,38} 比较4次
第三次归并:{1,6,8,38,100,202,301} 比较4次
总共比较次数为:3+4+4=11次
算法步骤:
第一步:申请空间temp(),使其大小为两个已经排序序列之和,该空间用来存放合并后的序列。
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一个位置。
重复步骤三直到某一指针超出序列尾
将另一个序列剩下的所有元素直接复制到合并序列尾部
#include <iostream>
#include <string>
#include <algorithm>
typedef long long LL;
LL cnt=0;
using namespace std;
//分别输入数组,数组左边下标,中间下标,右边下标,临时数组
//合并左边和右边
void print(LL a[],LL n){
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}
void mergearray(LL a[],LL left,LL mid,LL right,LL temp[]){
LL i=left,j=mid+1;
LL m=mid,n=right;
LL k=0;
//左边和右边分别进行循环
while(i<=m&&j<=n){
//左边小于右边就存进临时数组
if(a[i]<=a[j])
temp[k++]=a[i++];
else{
temp[k++]=a[j++];
//cnt+=m-i+1;
}
}
//将原始数组存进临时数组,
while(i<=m)
temp[k++]=a[i++];
for(i=0;i<k;i++)
a[left+i]=temp[i];
}
//排序
void mergesort(LL a[],LL left,LL right,LL temp[]){
if(left<right){
LL mid=(left+right)/2;
mergesort(a,left,mid,temp);
mergesort(a,mid+1,right,temp);
mergearray(a,left,mid,right,temp);
print(a,7);
}
}
bool MergeSort(LL a[],LL n){
LL *p=new LL[n];
if(p==NULL)
return false;
mergesort(a,0,n-1,p);
delete []p;
return true;
}
int main(){
LL a[]={6,202,100,301,38,8,1};
MergeSort(a,7);
for(int i=0;i<7;i++){
cout<<a[i]<<" ";
}
return 0;
}
一开始先对左边进行排序
{6,202},100,301,38,8,1
{6,202},{100,301},38,8,1
{6,100,202,301},38,8,1
左边排序完,对右边进行排序
{6,100,202,301},{8,38},1
{6,100,202,301},{1,8,38}
{1,6,8,38,100,202,301}
排序完成。
速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。