从头开始复习算法之归并排序

前一篇文章主要讲道理基础的几个算法,论其思想还是比较基础的,但是今天开始讲解的归并排序就不那么简单了。

关于归并排序呢?其实思想也并不是很麻烦,最核心的思想我就用简单的讲述方式给大家来讲述一下:

一、 简单的归并排序步骤

1.1、 初始化数据
A数组的指针数组A数组BB数组的指针
➡️24⬅️
-85-
-96-
-107-
数组C01234567
指针位置⬆️

如上表所示,存在两个递增的数组(A,B),然后将A,B数组的指针拨到数组的首位。另外存在一个数组C,长度是两个递增数组之和,并且将该数组的指针也拨到首位。

1.2、指针有条件的遍历数组
A数组的指针数组A数组BB数组的指针
-24⬅️
➡️85-
-96-
-107-
数组C01234567
指针位置⬆️
2

首先我们来判断A指针指向的数值和B指针指向的数值做比较,如果A指针的数值小于B指针的数值,就将A指针指向的数值填写到数组C中,并且将A,C指针同时指向其数组的下一位。

1.3、继续指针有条件的遍历数组
A数组的指针数组A数组BB数组的指针
-24-
➡️85⬅️
-96-
-107-
数组C01234567
指针位置⬆️
24

首先我们来判断A指针指向的数值和B指针指向的数值做比较,如果A指针的数值大于B指针的数值,就将B指针指向的数值填写到数组C中,并且将B,C指针同时指向其数组的下一位。

1.4、 继续重复重复

重复的操作直到一个数组遍历完全,最终的效果如下:

A数组的指针数组A数组BB数组的指针
-24-
➡️85-
-96-
-107-
-⬅️
数组C01234567
指针位置⬆️
24567
1.4、将可能剩余的A,B数据抄写到数组C中

当B指针遍历完B数组之后,就把剩下的A数组剩下的元素抄写到数组C中,就完成了归并排序。效果如下:

A数组的指针数组A数组BB数组的指针
-24-
-85-
-96-
-107-
➡️⬅️
数组C01234567end
指针位置⬆️
245678910
1.6、具体的代码如下:

就这样简简单单的几步操作就完成了 归并操作,是不是很简单呢?

好了,我们来简单的写一下代码。

在写代码之前,我们首先整理一下思维:前面说到的是存在两个有序的数组,明显我们在实际的操作中只可能给你一个数组做排序,我们可以创建一个数组,然后里面有两段有序的数列。如下所示:

[2,8,9,10,4,5,6,7]
复制代码

然后我们将两个有序数组择出来,再进行数组的遍历比较,将比较小的元素写在原数组中,直到一个数组被遍历完全,最后将另外一个没有遍历完数组的剩余元素抄写到原数组中。就得到新排序好的数组。具体的代码如下:

/**
 * arr = [2,8,9,10,4,5,6,7]
 * leftPos:数组的开始位置
 * midPos:数组的分割点
 * rightPos:数组的结束位置
 **/
function merge(arr,leftPos,midPos,rightPos){
	let leftArray = [];
	let rightArray=[];
	// 先将数组分成两个数组
	// arr = [2,8,9,10,4,5,6,7]
	for(let i=leftPos;i<=midPos;i++) {
		leftArray.push(arr[i]);
	}
	for(let i=midPos+1;i<=rightPos;i++) {
		rightArray.push(arr[i]);
	}
	let left = 0;
	let right=0;
	let pos=leftPos;
	// 指针的偏移
	while(left<leftArray.length && right<rightArray.length){
		if(leftArray[left]>rightArray[right]) arr[pos++] = rightArray[right++];
		else arr[pos++] = leftArray[left++];
	}
	// 剩余数据的抄写
	while(left<leftArray.length){
		arr[pos++] = leftArray[left++];
	}
	while(right<rightArray.length){
		arr[pos++] = rightArray[right++];
	}
	return arr;
}
复制代码

二、真正的归并排序来了

看了上面的分析可能会有这样的疑问呀:这种限制是不是太死了,需要两段有序的数列,哪有这么巧的事儿,这样的排序是不是在实际操作中到底有什么作用呢?

好了,针对这样的疑问,我们继续去完善我们的代码。首先在完善代码之前 我们得提到一个概念:分治

什么叫分治呢?我的理解就是分而治之,就是将完全没有顺序的数组,从当中一刀切开,分成两小份,如果两份是有序数组,就用上面的思想来归并,如果不是就非有序的新数组再从中切一刀...就这样不断切分,直到找到有序数组位置(数组里面只有一项,肯定是有序的)。然后再不断的向上归并。就得到了一个排序好的序列了。

有点懵逼,这货在讲什么?好,来看下面的示意图:

               [3 ,2 , 4, 1 , 10, 8, 9, 6]
                   |             |
              [3 ,2 ,4 ,1]  [ 10 , 8, 9, 6]
                  |  |          |     |
              [3 ,2] [4 ,1]  [10 ,8] [9 ,6]
               | |    | |     |  |    | |
              3 2   4 1       10 8    9 6
复制代码

首先我们将数组进行切分操作。

              [3 ,2 , 4, 1 , 10, 8, 9, 6]
                   |              |
              [3 ,2 ,4 ,1]  [ 10 , 8, 9, 6]
                 |     |        |      |
              [2 ,3] [1 ,4]  [8 ,10] [6 ,9]
复制代码

如上所示 我们将最底部的数据进行归并操作。得到4个有序数组,

              [3 ,2 , 4, 1 , 10, 8, 9, 6]
                   |              |
              [1 ,2 ,3 ,4]  [ 6 , 8, 9, 10]
复制代码

如上所示,我们将最底部的有序数列在进行归并,得到两个有序数列,这样的两个有序数组是不是就有点熟悉了,最后我们在运用一次归并就得到了一个有序的数列。

[ 1, 2, 3, 4, 6, 8, 9, 10 ]
复制代码

分治的思维就是分而治之,也叫大事儿化小,其具体的分治代码如下:

function sortArray(arr,left,right){
	if(left < right){	
		let mid = Math.floor((left+right)/2);
		sortArray(arr,left,mid)
		sortArray(arr,mid+1,right)
		arr = merge(arr,left,mid,right)
	}
	return arr;
}
复制代码

全套代码如下:

/**
 * arr = [2,8,9,10,4,5,6,7]
 * leftPos:数组的开始位置
 * midPos:数组的分割点
 * rightPos:数组的结束位置
 **/
function merge(arr,leftPos,midPos,rightPos){
	let leftArray = [];
	let rightArray=[];
	// 先将数组分成两个数组
	// arr = [2,8,9,10,4,5,6,7]
	for(let i=leftPos;i<=midPos;i++) {
		leftArray.push(arr[i]);
	}
	for(let i=midPos+1;i<=rightPos;i++) {
		rightArray.push(arr[i]);
	}
	let left = 0;
	let right=0;
	let pos=leftPos;
	// 指针的偏移
	while(left<leftArray.length && right<rightArray.length){
		if(leftArray[left]>rightArray[right]) arr[pos++] = rightArray[right++];
		else arr[pos++] = leftArray[left++];
	}
	// 剩余数据的抄写
	while(left<leftArray.length){
		arr[pos++] = leftArray[left++];
	}
	while(right<rightArray.length){
		arr[pos++] = rightArray[right++];
	}
	return arr;
}

function sortArray(arr,left,right){
	if(left < right){	
		let mid = Math.floor((left+right)/2);
		sortArray(arr,left,mid)
		sortArray(arr,mid+1,right)
		arr = merge(arr,left,mid,right)
	}
	return arr;
}
复制代码

说在最后

其实归并操作思想还是比较简单的,但是我昨天搞了差不多两个多小时,主要问题是在边界值的处理上面。不知道说啥了 去水午觉去了。

转载于:https://juejin.im/post/5cdd481f51882569677f81fd

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值