排序算法总结之归并排序

基本思想

设归并排序的当前区间是R[low..high],分治法的三个步骤是:

①分解:将当前区间一分为二,即求分裂点

②求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序;

③组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。

递归的终结条件:子区间长度为1(一个记录自然有序)。

将两个有序序列合并成一个新的有序序列。

①把 n 个记录看成 n 个长度为 1的有序子表;

②进行两两归并使记录关键字有序,得到 n/2 个长度为 2 的有序子表;

③重复第②步直到所有记录归并成一个长度为 n 的有序表为止。



重点:

1.分治的实现

2.合并的实现

分治,就是把整个集合的元素一直除2化分,一直化为到没有两个元素开始合并。

对于归并排序,其关键就在于“合并”,即如何将两个有序序列合并成一个新的有序序列。

合并的实现

  1. 定义变量i,j从0开始,分别指向A、B子序列的第一个数据;
  2. 比较i、j处的元素值,将较小的复制到一个临时数组
  3. 若i处的小,则i++;否则j处的小,则j++

排序动态效果:


Java实现代码:

package com.liuhao.sort;

import java.util.Arrays;

/**
 * @author liuhao
 * 归并排序的Java实现
 */

public class MergeSort {

	public static void mergeSort(DataWrap[] data){
		sort(data, 0, data.length - 1);
	}

	/**
	 * 对数组data从left到right范围内的数据进行归并排序
	 * @param data 待排序数组
	 * @param left
	 * @param right
	 */
	private static void sort(DataWrap[] data, int left, int right){
		if(left < right){
			//找到中间索引
			int center = (left + right) / 2;
			//对左边数组递归排序
			sort(data, left, center);
			//对右边数组递归排序
			sort(data, center+1, right);

			//合并
			merge(data, left, center, right);
		}
	}

	/**
	 * 将两个数组进行合并,归并前两个数组已经有序,归并后依然有序
	 * @param data 数组对象
	 * @param left 左数组的第一个索引
	 * @param center 左数组的最后一个元素索引,center+1是右数组的第一个元素索引
	 * @param right 右数租的最后一个元素索引
	 */
	private static void merge(DataWrap[] data, int left, int center, int right) {
		DataWrap[] tmpArr = new DataWrap[data.length];//用来存放比较的数组,用完复制回到原来的数组
		int mid = center + 1; //右数组的第一个元素索引
		//third记录中间数组的索引
		int third = left;
		int tmp = left;

		while(left <= center && mid <= right){
			//将两个数组中较小的放入临时数组
			if(data[left].compareTo(data[mid]) <= 0){
				tmpArr[third++] = data[left++];
			}
			else{
				tmpArr[third++] = data[mid++];
			}
		}

		//剩余部分依次放入中间数组
		while(mid <= right){
			tmpArr[third++] = data[mid++];
		}
		while(left <= center){
			tmpArr[third++] = data[left++];
		}

		//将中间数组中的内容复制到原数组
		while(tmp <= right){
			data[tmp] = tmpArr[tmp++];
		}

	}

	public static void main(String[] args) {
		DataWrap[] data = {
				new DataWrap(9, "")
				,new DataWrap(-16, "")
				,new DataWrap(21, "")
				,new DataWrap(23, "*")
				,new DataWrap(-30, "")
				,new DataWrap(-49, "")
				,new DataWrap(21, "")
				,new DataWrap(30, "")
				,new DataWrap(3, "")
				,new DataWrap(67, "")
				,new DataWrap(35, "")
				,new DataWrap(5, "")
		};

		System.out.println("排序之前:" + Arrays.toString(data));
		mergeSort(data);
		System.out.println("排序之后:" + Arrays.toString(data));
	}

}

代码实现效果:


算法分析

1、稳定性

归并排序是一种稳定的排序。

2、存储结构要求

可用顺序存储结构。也易于在链表上实现。

3、时间复杂度

对长度为n的文件,需进行 趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。

4、空间复杂度

需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。

时间: 2024-10-12 21:55:34

排序算法总结之归并排序的相关文章

图解排序算法(四)之归并排序

基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之). 分而治之 可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现).分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n. 合并相邻有序子序列 再来看看治阶段

排序算法之二路归并排序

基本思想 首先将待排序的元素序列分成两个长度相等的子序列,为每一个子序列排序,然后再将它们合并成一个序列. 代码 private void mergeSort(int[] a, int[] b, int left, int right) { if (left < right) { int middle = (left + right) / 2; mergeSort(a, b, left, middle); mergeSort(a, b, middle + 1, right); merge(a,

《算法导论》读书笔记之排序算法—Merge Sort 归并排序算法

自从打ACM以来也算是用归并排序了好久,现在就写一篇博客来介绍一下这个算法吧 :) 图片来自维基百科,显示了完整的归并排序过程.例如数组{38, 27, 43, 3, 9, 82, 10}. 在算法导论讲分治算法一章的时候提到了归并排序.首先,归并排序是一个分治算法. 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表, 即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列. merg() 函数是用来合并两个已有序的数组.  是整个算法的关键. 那么归并

排序算法二:归并排序(Merge sort)

归并排序(Merge sort)用到了分治思想,即分-治-合三步,算法平均时间复杂度是o(nlgn). (一)算法实现 1 private void merge_sort(int[] array, int first, int last) { 2 if (first + 1 < last) { 3 int mid = (first + last) / 2; 4 merge_sort(array, first, mid); 5 merge_sort(array, mid, last); 6 7 /

常用算法之排序算法四【归并排序】

归并排序是将排好序的序列逐步合成一个大序列的算法,从字面上来分析,主要分为归并和排序. 算法描述: 1.申请一块空间,大小为两个排好序序列长度之和,用来存放归并后的序列. 2.设两个指针,分别指向两个已经排好序的序列的起始地址. 3.比较两个指针指向位置的值大小,根据升序降序,选择较小值或者较大值存储在合并空间内,并将相应指针后移. 4.重复3操作,直至指针移至序列尾部. 5.将另一个序列的值全部合并至合并序列中. 先抛开描述,说说自己的理解,就是把一个短有序序列合并成一个新的长有序序列,就是它

排序算法入门之归并排序(java实现)

归并排序是采用分治法的典型应用. 参考<数据结构与算法分析-Java语言描述> 归并排序其实要做两件事: (1)"分解"--将序列每次折半划分. (2)"合并"--合并两个已排序的表. 合并:对于两个输入数组A和B,一个输出数组C,以及3个计数器Actr.Bctr.Cctr,他们的初始置于对应数组的开始端.A[Actr]和B[Bctr]中较小的拷贝到C中的下一个位置,相关的计数器向前推进一步.当两个输入表有一个用完时,则将另一个表中剩余的部分拷贝到C中.

排序算法学习之归并排序

1. 归并排序原理:有长度为n的子序列a[n],可以将其看做n个长度为1的子序列,将相邻子序列两两归并后子序列数量减少一半,再对子序列进行两两归并,数量又减少一般,重复直到得到一个长度为n的子序列 2. 实现归并操作的代码如下: /*array[s-m]和array[m+1-t]均已各自有序,合并使得array[s-t]有序*/ void Merge(int s, int m, int t, int *array) { int temp[t-s+1];/*设临时数组存放排序后的元素*/ int

JS实现常用排序算法—经典的轮子值得再造

关于排序算法的博客何止千千万了,也不多一个轮子,那我就斗胆粗制滥造个轮子吧!下面的排序算法未作说明默认是从小到大排序. 1.快速排序2.归并排序3.冒泡排序4.选择排序(简单选择排序)5.插入排序(直接插入排序)6.希尔排序二分查找 1.快速排序 为什么把快排放在最前面呢,因为传说Chrome中数组的sort方法默认采用的就是快排. 算法思想: (1)在数据集之中,选择一个元素作为"基准"(pivot). (2)所有小于"基准"的元素,都移到"基准&quo

排序算法总结之希尔排序

一,希尔排序算法介绍 ①希尔排序又称缩小增量排序 ,它本质上是一个插入排序算法.为什么呢? 因为,对于插入排序而言,插入排序是将当前待排序的元素与前面所有的元素比较,而希尔排序是将当前元素与前面增量位置上的元素进行比较,然后,再将该元素插入到合适位置.当一趟希尔排序完成后,处于增量位置上的元素是有序的. ②希尔排序算法的效率依赖于增量的选取 假设增量序列为 h(1),h(2).....h(k),其中h(1)必须为1,且h(1)<h(2)<...h(k) . 第一趟排序时在增量为h(k)的各个元