归并排序算法 递归及循环实现

第一步合并相邻长度为1的子数组段,这是因为长度为1的子数组段是已经排好序的。

用一次对数组arr的线性扫描就足以找出所有这些排好序的子数组段。然后将相邻的排好序的子数组段两两合并,构成更大的排好序的子数组段。

#include<stdio.h>
#include<iostream>
using namespace std;
//递归思想归并排序 
//void MergeSort(int a[],int left,int right){
//	if(left<right){
//		int i=(left+right)/2;//取中点 
//		MergeSort(a,left,i);
//		MergeSort(a,i+1,right);
//		MergeSort(a,b,left,i,right);//合并到数组b 
//		Copy(a,b,left,right);//复制会数组b	
//	}
//}

//循环思想归并排序
void Merge(int c[],int d[],int left,int mid,int right){
	int i=left,j=mid+1,k=left;
	while(i<=mid&&j<=right){
		if(c[i]<=c[j])d[k++]=c[i++];
		else d[k++]=c[j++];
	}
	if(i>mid)for(int q=j;q<=right;q++)d[k++]=c[q];//当i已经超过了mid时,说明跳出while循环时j可能<right,所以将剩余的mid~right之间的数据赋值给d数组 
	else for(int q=i;q<=mid;q++)d[k++]=c[q]; //说明i~mid之间可能有剩余数据,将其赋值给d数组 
}
void MergePass(int x[],int y[],int s,int n){
	int i=0;
	while(i<=n-s*2){//即i+s*2<=n,以i+s为中点的左右两边的总长不能超过n 
		Merge(x,y,i,i+s-1,i+s*2-1);
		i=i+s*2; 
	}
	if(i+s<n)Merge(x,y,i,i+s-1,n-1);
	else for(int j=i;j<=n-1;j++) y[j]=x[j];
}


void MergeSort(int a[],int n){
	int b[n];
	int s=1;
	while(s<n){
		MergePass(a,b,s,n);//将a->b  一次排序中的结果保存到b中 
		s+=s;
		MergePass(b,a,s,n);//将b->a  一次排序的结果保存到a中 
		s+=s;
	}
} 
int main(){
		int arr[5]={23,12,2,5,3};//测试数据 
		MergeSort(arr,5);
		for(int i=0;i<5;i++){
			printf("%d ",arr[i]);
		}
		return 0;
}
    原文作者:排序算法
    原文地址: https://blog.csdn.net/catkint/article/details/50900479
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞