(四)算法学习之归并排序

一、归并排序简介(自己理解)

自己的理解一句话:所谓归并排序,就是递归+合并。

引用百度百科对归并排序的定义:是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并点击打开链接

二、归并排序过程

过程:首先对数组进行无限对半分割,不断调用自身函数,也成递归。每次分割得到左右两个数组,对两边的数组分别进行排序,等到两边的数组都有序后,利用封装的merge函数对两个有序数组进行合并,最后得到整体有序。

其中无限分割最后应该分割到左右数组各只有一个元素,然后对两边的元素进行合并,再返回上层再合并。最终回到初始的数组上。

图解过程:


首先第一次分割,得到 [ 5 , 7 , 4 , 11 ] , [ 2 , 8 , 2 , 15 ] 两个数组,再往下分割,直至左右两个数组只有一个元素


分割完成后,对左右两边进行合并。

初始思路:新建一个数组,长度定义与原数组相同,定义三个指针,分别指向左数组第一个元素,右数组第一个元素和新定义数组的第一个元素,对原数组左右两部分分别遍历,想得到的较小的数传入新数组。最后将新数组的数据全部拷贝到原数组中。合并完成。

三、代码实现(Java)

public class MergeSort {
	public static void main(String[] args) {
		//获取指定长度的数组,getArray是自己封装的一个函数
		long[] arr1 = getArray(50000,500000);
		
		//获取两个时间相减,得到排序消耗的时间
		long startTime = new Date().getTime();
		mergeSort(arr1,0,arr1.length - 1);
		long endTime = new Date().getTime();
			
		int time = (int)(endTime - startTime);
		//打印数组
		printArray(arr1);
			
		System.out.println("\n" + time + "ms");
	}
	//归并排序的公共方法
	public static void mergeSort(long[] arr, int l, int r) {
		// TODO Auto-generated method stub
		long[] temp = new long[arr.length];
		_mergeSort(arr, l, r, temp);
	}
	//归并排序的私有方法
	private static void _mergeSort(long[] arr, int l, int r, long[] temp) {
		// TODO Auto-generated method stub
		if(r <= l) {
			return;
		}
		int mid = (l + r) / 2;
		_mergeSort(arr, l, mid, temp);		//左边排序
		_mergeSort(arr, mid + 1, r, temp);	//右边排序
		merge(arr,l, mid, r, temp);
			
	}	
	//合并两个有序数组arr[l,mid],arr[mid+1,r]
	private static void merge(long[] arr, int l, int mid, int r, long[] temp) {
		// TODO Auto-generated method stub
		int index, index1, index2;
		index = 0;
		index1 = l;
		index2 = mid + 1;
		while(index < r - l + 1) {
			if(index1 > mid) {
				temp[index ++] = arr[index2 ++];
			}else if(index2 > r) {
				temp[index ++] = arr[index1 ++];
			}else if(arr[index1] < arr[index2]) {
				temp[index ++] = arr[index1 ++];
			}else {
				temp[index ++] = arr[index2 ++];
			}
		}	
		
		for(int i = 0; i < r - l + 1; i ++) {
			arr[i + l] = temp[i];
		}
	}
}

四、代码运行结果

1、对50000个元素的数组进行排序

平均耗时:15ms

2、对500000个元素的数组进行排序

平均耗时:100ms

3、对5000000个元素的数组进行排序

平均耗时:1010ms

五、时间复杂度

归并排序属于较稳定且较高效算法

时间复杂度为:O(N*logN)

六、总结

归并排序相比较选择排序,直接插入排序和冒泡排序的效率要高的多,不过代码中还有很多值得优化的地方。例如:应该在调用私有函数前创建一个公共的副本数组,这样就不用每次递归都new一个新的数组,节省资源,效率稍微高一点。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值