归并排序是一个时间复杂度为O(nlogn)的算法,它可以由递归和非递归两种方式实现。
递归:
#include<iostream>
using namespace std;
void combine(int *nums,int l,int m,int r){
// cout<<"combine"<<l<<" "<<m<<" "<<r<<endl;
int len = r-l+1;
int *temp = new int[len+1];
int i = l;
int j = m+1;
int k =0;
while(i<=m && j <=r){
if(nums[i] >nums[j]){
temp[k++] = nums[j];
j++;
}else{
temp[k++] = nums[i];
i++;
}
}
while(i <=m) {temp[k++] = nums[i]; i++;}
while(j<=r) {temp[k++] = nums[j]; j++;}
k =0;
for(i =l;i<=r;i++) nums[i] = temp[k++];
delete []temp;
}
void merge_sort(int * nums,int left,int right){
if(left>=right) return;
int mid = (left+right)/2;
merge_sort(nums,left,mid);
merge_sort(nums,mid+1,right);
combine(nums,left,mid,right);
}
int main(){
int nums[] = {5,4,2,1,6,8,9,3};
int len = sizeof(nums)/sizeof(int);
cout<<"before sort:";
for(int i=0;i<len;i++) cout<<nums[i]<<" ";
cout<<endl;
merge_sort(nums,0,len-1);
cout<<"after sort:";
for(int i=0;i<len;i++) cout<<nums[i]<<" ";
return 0;
}
非递归实现:
#include<iostream>
using namespace std;
void combine(int *nums,int l,int m,int r){
// cout<<"combine"<<l<<" "<<m<<" "<<r<<endl;
int len = r-l+1;
int *temp = new int[len+1];
int i = l;
int j = m+1;
int k =0;
while(i<=m && j <=r){
if(nums[i] >nums[j]){
temp[k++] = nums[j];
j++;
}else{
temp[k++] = nums[i];
i++;
}
}
while(i <=m) {temp[k++] = nums[i]; i++;}
while(j<=r) {temp[k++] = nums[j]; j++;}
k =0;
for(i =l;i<=r;i++) nums[i] = temp[k++];
delete []temp;
}
void merge_sort(int * nums,int length){
for(int i = 1;i<length;i*=2){//枚举步长
int l = 0;
while(l<length-1){
int mid = l+i-1;
int r = mid +i;
if(mid>= length-1) break;//mid已经大于数组长度了,证明已经拍完
if(r>=length){ r = length -1;}//右边步长超过数组长度要退回到数组长
if(r ==mid) break;//只有左边,则排完了
combine(nums,l,mid,r);
l = r+1;
}
}
}
int main(){
int nums[] = {5,4,2,1,6,8,9,3};
int len = sizeof(nums)/sizeof(int);
cout<<"before sort:";
for(int i=0;i<len;i++) cout<<nums[i]<<" ";
cout<<endl;
merge_sort(nums,len);
cout<<"after sort:";
for(int i=0;i<len;i++) cout<<nums[i]<<" ";
return 0;
}