博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【分治】归并排序
阅读量:4091 次
发布时间:2019-05-25

本文共 3351 字,大约阅读时间需要 11 分钟。

目录

 


一、二路归并实现

递归实现,栈空间:O(logn)、堆空间:O(nlogn)

public static void mergeSort1(int[] arr) {  // 多做一层包装,简化用户输入		mergeSort1(arr, 0, arr.length-1);	}	public static void mergeSort1(int[] arr, int left, int right) {		int mid = (right+left) / 2;		if (left < right) {			mergeSort1(arr, left, mid);			mergeSort1(arr, mid+1, right);			merge1(arr, left, right, mid);		} 	}	public static void merge1(int[] arr, int left, int right, int mid) {		int[] temp = new int[right-left+1];		int i = left;		int j = mid+1;		int k = 0;		for (; i<=mid && j<=right; k++) {			if (arr[i] < arr[j]) {				temp[k] = arr[i];				i = i + 1;			} else {				temp[k] = arr[j];				j = j + 1;			}		}		// 两部分中哪一部分多出一些元素,就把该部分的所有元素直接加入temp数组		while (i <= mid) {			temp[k++] = arr[i++];		}		while (j <= right) {			temp[k++] = arr[j++];		}				// 将排好序的temp数组的所有元素写入原数组的指定位置		for (int l=0; l

二、二路归并的一点优化

上面的代码中因为每一趟都要新建一个数组temp来临时存放已经处理好的相对有序的数组,所以使用的堆空间为O(nlogn)。这里我们将使用的空间降到O(n),也就是整个过程只新建一个大小为n的数组。

递归实现,栈空间:O(logn)、堆空间:O(n)

public static void mergeSort2(int[] arr) {		int[] temp = new int[arr.length];		mergeSort2(arr, temp, 0, arr.length-1);	}	public static void mergeSort2(int[] arr, int[] temp, int left, int right) {		int mid = (right+left) / 2;		if (left < right) {			mergeSort2(arr, temp, left, mid);			mergeSort2(arr, temp, mid+1, right);			merge2(arr, temp, left, right, mid);		} 	}	public static void merge2(int[] arr, int[] temp, int left, int right, int mid) {		int i = left;		int j = mid+1;		int k = left;		for (; i<=mid && j<=right; k++) {			if (arr[i] < arr[j]) {				temp[k] = arr[i];				i = i + 1;			} else {				temp[k] = arr[j];				j = j + 1;			}		}		// 两部分中哪一部分多出一些元素,就把该部分的所有元素直接加入temp数组		while (i <= mid) {			temp[k++] = arr[i++];		}		while (j <= right) {			temp[k++] = arr[j++];		}				// 将排好序的temp数组的所有元素写入原数组的指定位置		for (int l=left; l<=right; l++) {			arr[l] = temp[l];		}	}

三、原地归并实现

我们再继续将堆空间的复杂度降为O(1)

递归实现,栈空间:O(logn)、堆空间:O(1)

public static void mergeSort3(int[] arr) {		//int[] temp = new int[arr.length];		mergeSort3(arr, 0, arr.length-1);	}	public static void mergeSort3(int[] arr, int left, int right) {		int mid = (right+left) / 2;		if (left < right) {			mergeSort3(arr, left, mid);			mergeSort3(arr, mid+1, right);			merge3(arr, left, mid, right);		} 	}	public static void merge3(int[] arr, int left, int mid, int right) {		int i = left;		int j=mid+1;		/*		while (i

四、二路归并的非递归实现

非递归实现,栈空间:O(1)、堆空间:O(nlogn)

public static void mergeSort4(int[] arr) {		int len = arr.length;		int k = 1;				while (k < len) {			mergePass(arr, k, len);			k *= 2;		}	}	public static void mergePass(int[] arr, int k, int n) {		int i = 0;		int j;				//从前往后,把2个(一对)长度为k的子序列合并为1个		while (i < n-2*k+1) {			merge(arr, i, i+k-1, i+2*k-1);			i += 2*k;		}				//这段代码保证了,将那些“落单的”长度不足两两merge的部分和前面merge起来		if (i < n-k) {			merge(arr, i, i+k-1, n-1);		}	}	public static void merge(int[] arr, int low, int mid, int high) {		//temp数组用于暂存合并的结果		int[] temp = new int[high-low+1];		//左半边的指针		int i = low;		//后半边的指针		int j = mid+1;		//合并后数组的指针		int k = 0;				//将记录从小到大(有序地)放进temp数组		for (; i<=mid && j<=high; k++) {			if (arr[i] <= arr[j]) {				temp[k] = arr[i++];			} else {				temp[k] = arr[j++];			}		}		//接下来的两个while循环是为了将一边剩余的(比另一边多出来的个数)放到temp数组中		while (i <= mid) {			temp[k++] = arr[i++];		}		while (j <= high) {			temp[k++] = arr[j++];		}				//将temp数组中的元素写入原数组中的对应位置		for (int l=0; l

五、在归并排序中使用直接插入排序

待续

 

转载地址:http://mbnii.baihongyu.com/

你可能感兴趣的文章
又一神书面世:《无需计算机的计算机科学》!
查看>>
微信支付的软件架构究竟有多牛逼...
查看>>
聊聊 5G 技术的那些事儿...
查看>>
微软当年挖下大坑,现砸重金买下危险域名 corp.com 来填!
查看>>
学不会数据结构与算法,是因为你还没看过这个图文并茂的算法中文课!
查看>>
这张「二维码」在 GitHub 上火了:扫一扫,打破系统边界,文件秒传
查看>>
霸榜 GitHub,一款开源的 Linux 神器!
查看>>
我不信这些技术名词的发音你都能读对!
查看>>
太赞了,亚马逊免费对外开放计算机编程课!
查看>>
如何画出一张优秀的架构图?
查看>>
论文代码不开源,应该被直接拒稿?
查看>>
教你一招搞定 Homebrew 下载加速!
查看>>
一个神奇的开源项目:让照片快速 3D 化!
查看>>
你肯定没用过这个全新的 Git 客户端工具!
查看>>
学生党 10 分钟搭了一个网站,后来净赚 100 万美金....
查看>>
雷军 1994 年写的代码,不服不行...
查看>>
GitHub 热榜:印度小哥在《我的世界》搭建神经网络,火爆全网!
查看>>
GitHub 开源神器:堪称作业终结者!
查看>>
Spring 面试五连问,问到你怀疑人生!
查看>>
C++ 是如何从代码到游戏的?
查看>>