八种排序算法之六:详解归并排序

2023-11-12

归并排序的核心思想首先可以从一个问题入手:

如果我们在排序时遇到以下两个数组有序数组,有没有一种最快速的方法排序呢?
在这里插入图片描述
在这里插入图片描述对我们而言,把两个数组合成有序数列如果用之前的方法在遍历一遍太过麻烦,最快速度方法应该是像榫卯结构一样直接插入
在这里插入图片描述
有了思路,接下来就是我们如何把这一思想转化为计算机语言了
我们先新建一个长度为上面两个数组长度之和的新数组,然后比较两个数组的第一个元素,在如图中,是1和2比较,我们把较小的数组1拿出来放在新数组的首个
在这里插入图片描述
接下来比较左面数组的第二个和右面数组的第一个,把较小数放在数组的第二个位置,以此比较,放置,排序完成。

我们先通过代码来实现这一步:


package demo4;

import java.util.Arrays;

/**
 * 归并排序
 * 
 *
 * 2019年2月14日
 */
public class MergeSort {
	
	public static void main(String[] args) {
		int[] arr = new  int[]{1,3,5,7,9,2,4,6};
		System.out.println(Arrays.toString(arr));
		merge(arr,0,4,7);
		System.out.println(Arrays.toString(arr));
	}
	
	//创造开始,中间,结束位置的变量,目的是把一个数组拆成两个
	public static void merge(int[] arr,int low,int middle,int high){
		
		//创造归并后的临时数组
		int[] temp =new int[arr.length];
		//记录第一个数组需要遍历的下标
		int i =low;
		//记录第二个数组需要遍历的下标
		int j = middle+1;
		//用于记录在临时数组中存放的下标
		int index = 0;
		System.out.println("i="+i+" "+"j="+j);
		//遍历两个数组去除小弟数字,放入临时数组
		while(i<=middle&&j<=high){
			//第一个数组的数更小
			if(arr[i]<arr[j]){
				temp[index]=arr[i];
				//下标后移
				i++;
				index++;
			}else{//第二个数组更小
			    temp[index]=arr[j];
			    j++;
			    index++;
			}
		}
		//处理多余的数据(两个数组不等长,一方比完跳出循环)
		//直接把剩余元素追加到数组之后
		while(j<=high){
			temp[index]=arr[j];
			j++;
			index++;
		}
		
		while(i<=middle){
			temp[index]=arr[i];
			i++;
			index++;
		}
		
		//把临时数组赋给原数组
		for(int n=0;n<arr.length;n++){
			arr[n]=temp[n];
		}
	}

}

在这里插入图片描述

运行结果无误,但是我们可不可以把这个方法给推广一下呢,对于任意混乱数组也可以使用此方法排序?


解决了以上的问题,我们就可以解释归并排序的核心思想:
就是先把数组拆分为两部分,再继续拆分下去,直到被拆为单个元素组成的数组,然后相邻的小数组进行比较,排序,合并,小数组就不断吸收其他元素,演变为两个中等数组的比较,最后变成数组的两部分之间的排序合并问题,问题就变成了我们刚才解决的问题了:
两个有序数组之间的合并排序?

那么对于单个元素,我们刚才的这个方法是否有效?
经检验,是可以的——
在这里插入图片描述
这样问题就转化为了如何利用递归的思想,让数组从单个元素的“小数组”一直排序到两部分的大数组。

先调用自身拍好左面的数组,在排好右面的,之后把两部分归并

// 归并排序
	public static void mergeSort(int[] arr, int low, int high) {
		int middle = (high + low) / 2;
		if (low < high) {
			mergeSort(arr, low, middle);
			mergeSort(arr, middle + 1, high);
			// 两个数组被拆分完成,进行归并的操作
			merge(arr, low, middle, high);
		}
	}

运行结果如下:
在这里插入图片描述
全部代码如下:


package demo4;

import java.util.Arrays;

/**
 * 归并排序
 * 
 *
 * 2019年2月14日
 */
public class MergeSort {

	public static void main(String[] args) {
		int[] arr = new int[] {5,7,6,9,4,2,3,8};
		System.out.println("原数组" + Arrays.toString(arr));
		mergeSort(arr, 0, arr.length - 1);
		System.out.println("排序后" + Arrays.toString(arr));
	}

	// 归并排序
	public static void mergeSort(int[] arr, int low, int high) {
		int middle = (high + low) / 2;
		if (low < high) {
			mergeSort(arr, low, middle);
			mergeSort(arr, middle + 1, high);
			// 两个数组被拆分完成,进行归并的操作
			merge(arr, low, middle, high);
		}
	}

	// 创造开始,中间,结束位置的变量,目的是把一个数组拆成两个
	public static void merge(int[] arr, int low, int middle, int high) {

		// 创造归并后的临时数组
		int[] temp = new int[high-low+1];
		// 记录第一个数组需要遍历的下标
		int i = low;
		// 记录第二个数组需要遍历的下标
		int j = middle + 1;
		// 用于记录在临时数组中存放的下标
		int index = 0;
		// 遍历两个数组去除小弟数字,放入临时数组
		while (i <= middle && j <= high) {
			// 第一个数组的数更小
			if (arr[i] < arr[j]) {
				temp[index] = arr[i];
				// 下标后移
				i++;
				index++;
			} else {// 第二个数组更小
				temp[index] = arr[j];
				j++;
				index++;
			}
		}
		// 处理多余的数据(两个数组不等长,一方比完跳出循环)
		// 直接把剩余元素追加到数组之后
		while (j <= high) {
			temp[index] = arr[j];
			j++;
			index++;
		}

		while (i <= middle) {
			temp[index] = arr[i];
			i++;
			index++;
		}

		// 把临时数组赋给原数组
		for (int n = 0; n < temp.length; n++) {
			arr[n+low] = temp[n];
		}
	}

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

八种排序算法之六:详解归并排序 的相关文章

随机推荐

  • 官网下载Eclipse历史版本

    官网下载Eclipse历史版本 Eclipse官网 downloads路径 https www eclipse org downloads 点击 Download Packages 点击 Download Packages 选择你想要的版本
  • Idea 断点调试PHP

    老实说 我尝试过xdebug 但是说实话 没一次成功过 看来我还是 经验不足 简单的方法 前期工作需要装上xdebug 在php ini 末尾加上 XDebug 这是xdebug的dll 需要到官网上下载 需要注意区分自己的PHP是线程安全
  • Jordan Lecture Note-12: Kernel典型相关分析(Kernel Canonical Correlation Analysis, KCCA).

    Jordan Lecture Note 12 Kernel典型相关分析 Kernel Canonical Correlation Analysis KCCA Kernel典型相关分析 一 KCCA 同样 我们可以引入Kernel函数 通过非
  • 华为培训 05 PON EPON GPON

    学习目标 PON架构 EPON主要技术 GPON主要技术 EPON 基于以太网方式的无源光网络 GPON 千兆无源光网络 1 PON网络加架构
  • 2022电大国家开放大学网上形考任务-客户关系管理非免费(非答案)

    客户关系管理形考作业一答案 试题 1 1 不是常用的市场营销组合理论 A 4C 理论 B 4P 理论 C 4A 理论 D 4S 理论 试题 2 2 企业实施客户关系管理的作用主要体现在提升企业竞争优势 提高客户满意度 以及提升企业销售业绩
  • 【Verilog 常见设计】(0)二进制码和格雷码互转 Verilog 实现

    目录 格雷码介绍 转化原理 Verilog 实现 testbench 测试代码 仿真波形 格雷码介绍 在一组数的编码中 若任意两个相邻的代码只有一位二进制数不同 则称这种编码为格雷码 Gray Code 另外由于最大数与最小数之间也仅一位数
  • uniapp原生插件-YL视频播放器

    YL视频播放器uniapp插件市场地址 https ext dcloud net cn plugin id 9569 简介 YL视频播放器是一款适用于安卓端的高性能原生插件 ios暂不支持 支持3核心切换 exo ijk 安卓原生 支持点播
  • 【ChatGPT】500个ChatGPT/GPT-4 Prompt技巧

    文章目录 一 前言 二 什么是Prompt Engineering 三 ChatGPT GPT 4 Prompt Engineering使用技巧 一 前言 随着 GPT 4 和 DALL E等大型 强大的生成式 AI 模型变得更好 更可用
  • 分布式锁-Redisson

    目录 1 分布式并发问题 2 如何解决分布式并发问题呢 3 使 Redis实现分布式锁 代码实现 4 解决因线程异常导致 法释放锁的问题 5 解决因t1过期释放t2锁的问题 6 看 狗机制 7 分布式锁框架 Redisson 7 1 Red
  • MOS管为什么会存在寄生电感

    说到MOS管的寄生参数 我们一般都只想到mos管各极间的寄生电容 很少会想到MOS管的寄生电感 其实分立的MOS管它是存在寄生电感的 并且栅极 源极和漏极都存在 在一些MOS的数据手册会提到这个寄生电感 那么MOS管寄生电感是怎么产生的呢
  • 如何将VB6项目部署到服务器上,如何将整个VB6项目保存到新文件夹?模块和所有...

    Option Explicit Public VBInstance As VBIDE VBE Public Connect As Connect Private Sub CancelButton Click Connect Hide End
  • 使用oracle的trunc和dbms_random.value随机取n条数据

    场景 今天在review项目代码的时候看到这样一个问题 有一张号码表 每次需要从这样表中随机取6个空闲的号码 也就是每次取出来的6个号码应该都会有所不同 然后我就看到了这样的SQL select t from tel number tbl
  • 个人博客--小小笔记2

    目录 一 博客登录 1 JWT技术 03 md 1 1 jwt介绍 1 2 jwt使用 2 利用token JWT 编写登录方法 2 1实现jwt 2 2jwt存放缓存redis中 以便后期检测是否登录 3 统一错误码 减少大量重复繁琐的返
  • jenkins定时构建时间设置

    举几个例子 每隔5分钟构建一次 H 5 每两小时构建一次 H H 2 每天中午12点定时构建一次 H 12 每天下午18点定时构建一次 H 18 在每个小时的前半个小时内的每10分钟 H 0 29 10 每两小时45分钟 从上午9 45开始
  • 蓝牙 BLE 协议学习: 有关概念介绍

    背景 在学校内就用过蓝牙技术参加过比赛 并拿了奖 而蓝牙作为物联网中比较常见的协议 有必要进行深入的学习 此后的文章会以 ble v4 0 进行学习 介绍 蓝牙技术最初由电信巨头爱立信公司于 1994 年创制 当时是作为 RS232 数据线
  • 学计算机编程我有什么好处,编程是什么 学习编程的好处

    在科技快速发展的今天 很多人都会问编程是什么 学习编程有什么好处 下面有途网小编就带大家整理了一下 希望可以给你们带来帮助 编程是什么 编程是编写程序的中文简称 就是让计算机代为解决某个问题 对某个计算体系规定一定的运算方式 使计算体系按照
  • <QT>把日志输出打印在终端

    在 pro文件中 CONFIG行后添加 console CONFIG c 11 console
  • JSON View谷歌浏览器插件使用

    下载JsonView扩展程序压缩包 解压这个压缩包 打开谷歌浏览器的扩展程序界面 方式一 在谷歌浏览器地址栏中输入 chrome extensions 方式二 加载JsonView扩展程序 选中开发者模式 点击 加载正在开发的扩展程序 选择
  • Matlab在一张图上画多条曲线或分别画

    1 在plot曲线时 有时想在一张图上重合画多条曲线 我们只需要在画图命令之前加上hold on就好 比如 t 1 0 1 10 y1 sin 2 pi t y1 cos 2 pi t plot y1 hold on plot y2 运行结
  • 八种排序算法之六:详解归并排序

    归并排序的核心思想首先可以从一个问题入手 如果我们在排序时遇到以下两个数组有序数组 有没有一种最快速的方法排序呢 对我们而言 把两个数组合成有序数列如果用之前的方法在遍历一遍太过麻烦 最快速度方法应该是像榫卯结构一样直接插入 有了思路 接下