MergeSort

MergeSort 归并排序

主要说明优化的过程,如讲解过程不明了,请见 源码

  • 简介

    归并排序是将数组不断二分(divide)至单节点/双节点,排序后再逐一合并(merge)回原始数组的算法

    其实现过程是分治(divide and conquer)的典例

  • 概述

    1. sort0(); 主要是将数组长度分为奇偶的情况进行 divide,merge 两种情况通吃

      相对 sort1 而言数组拷贝的次数较少

    2. sort1(); 通过二分法(binary divide)& 后序合并(post-order merge)

      相对 sort0 而言代码更简单直接,奇偶情况合并处理

    3. sort2();

      结合 sort0 & sort1 的优势,主要优化的方面是减少数组拷贝的次数,减少内存消耗

  • 说明

    AnyType 为 non-static 类型,而排序方法需要是 static 方法

    所以引入泛型后,无法对 AnyType array[] 成员化

    解决方案:作为参数传递

sort0

  • 算法实现

    1. divide 分奇偶情况以及原数组长度为 1 的特殊情况

      奇数长度的情况,去除尾元素,剩余的偶数长度交由偶情况处理

      各个 subarray 分至 length == 1 后开始 merge 操作

    2. merge 分 单元素 + array 合并 & array1 + array2 合并 两种情况

      通过比较两个(已排序)数组,将较小值逐一放置到数组中

      实际上这是后期作为优化合并多种情况,从而简化代码

    3. merge 结果作为 subarray 的新对象,即通过改变引用指向已排序数组

      merge 过程即 sort 过程,merge 与 divide 相反,subarray 长度逐渐增加直到原数组长度

  • 举个例子

将下面数组通过 MergeSort.sort0(); 实现排序

5871314416

首先左边分至单元素数组

在这里插入图片描述

其次进行合并

在这里插入图片描述

同理处理右边

在这里插入图片描述

合并刚排序的左右边,以及最初分离的末尾元素

在这里插入图片描述

  • 代码实现
/* 
 * divide until single node, then merge from deep to shallow,
 * which means the length of arrays increases with the merge
 * and the arrays are sorted when merge
 */
public static<AnyType extends Comparable<AnyType>> 
void sort0(AnyType array[]) {
	if(array.length <= 1) {
		return;
	}
	/*
	 * ERROR on use `array = divide(array)`; which only change the formal parameter
	 * technically only change formal parameter points to the new array[], 
	 * but actual parameter still points to original array[],
	 * which means it didn't change the actual parameter at all
	 */
	AnyType tmpArray[] = divide(array);
	for(int i = 0; i < tmpArray.length; i++) { //so change the elements of original array one by one
		array[i] = tmpArray[i]; //which are in heap
	}
}

/*
 * divide the array that we get
 */
@SuppressWarnings("unchecked")
private static<AnyType extends Comparable<AnyType>>
AnyType[] divide(AnyType array[]) { 
	
	/*
	 * odd divide -> evenArray + single element -> merge back into array
	 */
	if(array.length % 2 != 0 && array.length != 1) { //length >= 3
		AnyType tmpArray[] = (AnyType[]) new Comparable[array.length-1];
		for(int i = 0; i < tmpArray.length; i++) {
			tmpArray[i] = array[i];
		}
		tmpArray = divide(tmpArray);
		return merge(tmpArray, array[array.length-1]);
	}

	AnyType array1[] = (AnyType[]) new Comparable[array.length/2];
	AnyType array2[] = (AnyType[]) new Comparable[array.length/2];
	/*
	 * equally divide array into array1 & array2
	 */
	for(int i = 0; i < array1.length; i++) {
		array1[i] = array[i];
		array2[i] = array[i+array1.length];
	}
	
	if(array1.length != 1) {
		array1 = divide(array1);
		array2 = divide(array2);
	}
	
	return merge(array1, array2);
}

/*
 * merge array1 & array2 into array
 * case include evenMerge & oddMerge
 */
@SuppressWarnings("unchecked")
private static<AnyType extends Comparable<AnyType>>
AnyType[] merge(AnyType array1[], AnyType array2[]) {
	AnyType array[] = (AnyType[]) new Comparable[array1.length + array2.length];
	int index1 = 0;
	int index2 = 0;
	int index; //array.index
	for(index = 0; index < array.length; index++) {
		if(index1 == array1.length || index2 == array2.length) {
			break;
		}
		if(array1[index1].compareTo(array2[index2]) < 0) {
			array[index] = array1[index1++];
		} else {
			array[index] = array2[index2++];
		}
	}
	if(index1 == array1.length) {
		for(; index2 < array2.length; index2++) {
			array[index++] = array2[index2];
		}
	} else {
		for(; index1 < array1.length; index1++) {
			array[index++] = array1[index1];
		}
	}
	return array;
}

/*
 * merge a element & an array
 * of course treat theElement as an single node array
 */
@SuppressWarnings("unchecked")
private static<AnyType extends Comparable<AnyType>>
AnyType[] merge(AnyType[] tmpArray, AnyType theElement) { //odd only
	AnyType array[] = (AnyType[]) new Comparable[1];
	array[0] = theElement;
	return merge(array, tmpArray);
}

sort1

  • 算法实现

    1. 二分法 divide + 后序 merge

    2. divide 至双节点数组时,开始 merge sort 操作(同样包含单节点情况)

    3. merge odd even 通吃,原数组 length == 1 也包含在内

      array --copy 所需位置元素–> tmpArray --sort 数据回馈–> array

      tmpArray 自始至终都是 array.length 的长度,难免在 Heap 中有过多 NULL 对象

      数组拷贝次数过多,无形消耗内存,同时这也是 sort2 所优化的内容

    4. merge 都是连续的元素,所以只给定三个位置参数,leftEnd 由 rightStart 给出

  • 举例说明

divide 过程与 sort0 divide 相似,但顺序 & 分割节点数略有不同,详见图

在这里插入图片描述

主要看 merge 过程,见图

在这里插入图片描述

注意: 图中节点为相对位置,即 divide 深度的简化图,而非实际数组下标

这里合并的过程类似后序的方式

拆分的最小数组含 2 个元素

当然也可能因为上一层的元素只有奇数个

而下层拆分时出现单元素的情况

这里奇偶情况通吃,是对 sort0 的改进简化

  • 代码实现
@SuppressWarnings("unchecked")
public static<AnyType extends Comparable<AnyType>> void sort1(AnyType array[]) {
	AnyType tmpArray[] = (AnyType[]) new Comparable[array.length];
	divide(array, tmpArray, 0, array.length); //[start, end);
}

private static<AnyType extends Comparable<AnyType>> 
void divide(AnyType array[], AnyType tmpArray[], int leftStart, int rightEnd) {
	/*
	 * binary divide + post-order merge
	 * @see BinarySearch in algorithm
	 */
	if(leftStart < rightEnd-1) {
		int center = (leftStart + rightEnd) / 2; //== leftStart + (rightEnd - leftStart) / 2;
		divide(array, tmpArray, leftStart, center);
		divide(array, tmpArray, center, rightEnd);
		merge(array, tmpArray, leftStart, center, rightEnd);
	}
}

private static<AnyType extends Comparable<AnyType>> 
void merge(AnyType[] array, AnyType[] tmpArray, int leftStart, int rightStart, int rightEnd) {
	int leftEnd = rightStart;
	int index = leftStart;
	int numOfElements = rightEnd-leftStart;

	while(leftStart < leftEnd && rightStart < rightEnd) {
		if(array[leftStart].compareTo(array[rightStart]) < 0) {
			tmpArray[index++] = array[leftStart++];
		} else {
			tmpArray[index++] = array[rightStart++];
		}
	}
	
	while(leftStart < leftEnd) {
		tmpArray[index++] = array[leftStart++];
	}
	
	while(rightStart < rightEnd) {
		tmpArray[index++] = array[rightStart++];
	}
	
	for(int i = 0; i < numOfElements; i++) {
		array[--rightEnd] = tmpArray[rightEnd];
	}
	
}
  • 对比 sort0 & sort1 divide 过程

在这里插入图片描述

可见拆分的顺序以及节点数量并不相同

根据对比可知,sort0 拆分最小单元为单节点,sort1 拆分最小单元为双节点

  • 对比 sort0 & sort1 merge 过程

在这里插入图片描述

可见合并的顺序以及节点数量并不相同,实际上合并的次数也不相同

sort2

  • 结合 sort0 & sort1 的优点

    1. 通过返回已排序数组,++改变原数组的指向++,减少数组拷贝

    2. ++二分法拆分 + 后序合++并,简化代码,合并奇偶处理

由于代码重复度高,所以在此不作详细解释,详细见 MergeSort

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
系统根据B/S,即所谓的电脑浏览器/网络服务器方式,运用Java技术性,挑选MySQL作为后台系统。系统主要包含对客服聊天管理、字典表管理、公告信息管理、金融工具管理、金融工具收藏管理、金融工具银行卡管理、借款管理、理财产品管理、理财产品收藏管理、理财产品银行卡管理、理财银行卡信息管理、银行卡管理、存款管理、银行卡记录管理、取款管理、转账管理、用户管理、员工管理等功能模块。 文中重点介绍了银行管理的专业技术发展背景和发展状况,随后遵照软件传统式研发流程,最先挑选适用思维和语言软件开发平台,依据需求分析报告模块和设计数据库结构,再根据系统功能模块的设计制作系统功能模块图、流程表和E-R图。随后设计架构以及编写代码,并实现系统能模块。最终基本完成系统检测和功能测试。结果显示,该系统能够实现所需要的作用,工作状态没有明显缺陷。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。进入银行卡列表,管理员可以进行查看列表、模糊搜索以及相关维护等操作。用户进入系统可以查看公告和模糊搜索公告信息、也可以进行公告维护操作。理财产品管理页面,管理员可以进行查看列表、模糊搜索以及相关维护等操作。产品类型管理页面,此页面提供给管理员的功能有:新增产品类型,修改产品类型,删除产品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值