高效排序方法之一 —— 归并排序

一、归并排序

 归并排序属于分治算法的一种,所谓分而治之,本质就是讲一个大规模的问题分解为若干个规模较小的相同子问题。大致过程如下:

  1. 将待排序元素分成大小大致相同的两个子序列
  2. 对两个子序列进行排序
  3. 将排好序的有序子序列进行合并,得到最终的有序序列

 

二、算法图解

 

 用一张图就可以对这个过程有一个清晰的了解了~

通过这张图就可以清晰的体会到分而治之的思想,就是先把一个无序数组通过递归分成多个小数组,然后对小数组进行排序,再去合并成一个大数组即可。 

 

 三、具体过程

这时候就说说核心算法的具体实现。首先为了进行合并,引入一个辅助合并函数Merge(),这个函数将排好序的两个子序列A[low, mid]和A[mid+1, high]进行合并(low,high是上下界,mid处于最中间位置)。

先建立一个辅助数组B[],设置三个辅助指针i,j,k;i和j分别指向两个待排序子序列当前待比较的元素,而k是指向B[]中待放置元素的位置。然后就在while循环中比较A[i]和A[j],把小的值给B[k],然后i++, j++,就是指针向后移继续比较,一直到所有的元素比较完后就可以了,这时再把B中的辅助到A数组中即可。对应代码为:

while(i <= mid && j <= high){
    if(A[i] <= A[j])
        B[k++] = A[i++];
    else
        B[k++] = A[j++];

主要还是通过递归的方法来解决这个问题

 

四、实例代码

#include <iostream>
#include <cstdlib>
#include <cstdio> 

using namespace std;
 
void Merge(int A[], int low, int mid, int high){ 
	//辅助合并数组Merge,该函数将排好序的两个子序列进行合并 
	int *B = new int[high - low + 1];
	int i = low, j = mid + 1, k = 0;
	//开始合并 
	while(i<=mid && j<=high){
		if(A[i] > A[j]){
			//将较小元素放入B数组中 
			B[k++] = A[j++];
		} else {
			B[k++] = A[i++];
		}
	}
	//对剩余的做处理
	while(i <= mid )	B[k++] = A[i++];
	while(j <= high )	B[k++] = A[j++];
	//把B复制到A中
	for(i = low, k = 0; i<=high; i++){
		A[i] = B[k++];
	} 
	delete []B;  //释放空间
}

void MergeSort(int A[], int low, int high){
	if(low < high){  
		int mid = (low+high)/2;
		//先划分 
		MergeSort(A,low,mid);
		MergeSort(A,mid+1,high);
		//再合并 
		Merge(A, low, mid, high);
	} 
}

int main( void ) {
	int n,A[100];  
	cout<<"number:"<<endl;
	cin >> n;
	cout<<"input :"<<endl;
	for(int i=0; i<n; i++){
		cin >>A[i]; 
	}
	MergeSort(A,0,n-1);
	cout<<"after sort :"<<endl;
	for(int i=0; i<n; i++){
		cout<<A[i]<<" ";
	}
	return 0;
} 
// 分解简单,合并操作难

时间复杂度:O(nlogn)

 

五、小结

总的来说,归并排序这个算法综合来看还是比较全面的,性能可以,虽然比快排慢了点,可以从下图看出:

但是在时间复杂度都相同的情况下比快排要稳定,所以这也算是归并的一个优势吧。

时间(ms)

10^3

10^4

10^5

10^6 

冒泡排序

0.545

61

8174

549432

选择排序

0.488

47

4717

478694

插入排序

0.764

56

5145

515621

堆排序

0.041

0.531

6.506

79

快速排序

0.030

0.311

3.634

39

归并排序

0.066

0.561

5.480

70

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值