老生常谈比较排序之归并排序(递归)
作者:jingxian 发布时间:2022-05-15 11:43:15
标签:归并排序,递归
归并排序里运用到算法里很重要的一个思想——分治法:将原问题分解为几个规模较小但类似于原问题的子问题——《算法导论》。
在每一层递归中都有3个步骤:
1.分解问题
2.解决问题
3.合并问题的解
举例待排序数组:{6, 5, 3, 1, 7, 2, 4},将它原始序列做分解。
可以经过不断的递归分解可以看到已经把原始数组序列不断分解为最小单位,接下来不妨将它们看做是二叉树的叶子节点。
将他们进行两两归并排序形成二叉树(也称为2路归并算法),可见二叉树的根节点即为最终序列。在这个过程中我们完成了剩余的两个步骤:解决问题和合并问题。
理论很简单,实践很“复杂”。对于归并排序的理论从上面的二叉树就看的很明白,将原始待排序数组不断分解最后看成是二叉树的叶子节点,再把它们两两排形成新的节点,逐渐归并为一个节点,此时的节点即为排好序的数组序列。
Java
package com.algorithm.sort.merge;
import java.util.Arrays;
/**
* 归并排序(递归)
* Created by yulinfeng on 2017/6/23.
*/
public class Merge {
public static void main(String[] args) {
int[] nums = {6, 5, 3, 1, 7, 2, 4};
nums = mergeSort(nums);
System.out.println(Arrays.toString(nums));
}
/**
* 归并排序
* @param nums 待排序数组序列
* @return 排好序的数组序列
*/
private static int[] mergeSort(int[] nums) {
segment(nums, 0, nums.length - 1);
return nums;
}
/**
* 递归切分待排
* @param nums 待切分数组
* @param left 待切分最后第一个元素的索引
* @param right 待切分数组最后一个元素的索引
*/
private static void segment(int[] nums, int left, int right) {
if (left >= right)
return;
// 找出中间索引
int center = (left + right) / 2;
// 对左边数组进行递归
segment(nums, left, center);
// 对右边数组进行递归
segment(nums, center + 1, right);
// 合并
merge(nums, left, center, right);
}
/**
* 两两归并排好序的数组(2路归并)
* @param nums 带排序数组对象
* @param left 左边数组的第一个索引
* @param center 左数组的最后一个索引,center + 1右数组的第一个索引
* @param right 右数组的最后一个索引
*/
private static void merge(int[] nums, int left, int center, int right) {
int[] tmpArray = new int[nums.length];
int rightIndex = center + 1; // 右数组第一个元素索引
int tmpIndex = left; //临时数组索引
int begin = left; // 缓存左数组第一个元素的索引,用于将排好序的数组拷贝回原数组
while (left <= center && rightIndex <= right) {
if (nums[left] <= nums[rightIndex]) {
tmpArray[tmpIndex++] = nums[left++];
} else {
tmpArray[tmpIndex++] = nums[rightIndex++];
}
}
while (left <= center) {
tmpArray[tmpIndex++] = nums[left++];
}
while (rightIndex <= right) {
tmpArray[tmpIndex++] = nums[rightIndex++];
}
while (begin <= right) {
nums[begin] = tmpArray[begin++];
}
}
}
Python3
#二路归并排序(递归)
def merge_sort(nums):
segment(nums, 0, len(nums) - 1)
return nums
#切分待排序数组
def segment(nums, left, right):
if left >= right:
return
center = int((left + right) / 2)
segment(nums, left, center)
segment(nums, center + 1, right)
merge(nums, left, center, right)
#两两归并排好序的数组(二路归并)
def merge(nums, left, center, right):
tmpArray = [0] * len(nums)
rightIndex = center + 1 #右数组的第一个元素索引
tmpIndex = left
begin = left
while left <= center and rightIndex <= right:
if nums[left] <= nums[rightIndex]:
tmpArray[tmpIndex] = nums[left]
tmpIndex += 1
left += 1
else:
tmpArray[tmpIndex] = nums[rightIndex]
tmpIndex += 1
rightIndex += 1
while left <= center:
tmpArray[tmpIndex] = nums[left]
tmpIndex += 1
left += 1
while rightIndex <= right:
tmpArray[tmpIndex] = nums[rightIndex]
tmpIndex += 1
rightIndex += 1
while begin <= right:
nums[begin] = tmpArray[begin]
begin += 1
nums = [6, 5, 3, 1, 7, 2, 4]
nums = merge_sort(nums)
print(nums)
0
投稿
猜你喜欢
- android大家都有很多需要用户上传头像的需求,有的是选方形,有的是圆角矩形,有的是圆形。首先我们要做一个处理图片的自定义控件,把传入的图
- 下面给大家分享一个有趣的动画:这里比较适合一张图片的翻转,如果是多张图片,可以参考APIDemo里的例子,就是加个ArrayAdapter,
- SpringBoot对actuator进行关闭management: endpoint: health
- 本文实例讲述了Java线程池用法。分享给大家供大家参考,具体如下:一 使用newSingleThreadExecutor创建一个只包含一个线
- 本文实例讲述了C#静态static的用法,分享给大家供大家参考。具体用法分析如下:一、静态类静态类与非静态类的重要区别在于静态类不能实例化,
- 本文实例讲述了C#获取USB事件API。分享给大家供大家参考。具体如下:const int WM_DEVICECHANGE = 0x2190
- 1.问题:昨天把项目打包放到国产中间件东方通(外部容器,功能类似Tomcat)上时,发现某些请求下载文件的接口不能正确返回文件,而是返回一个
- java弱口令检测机制1. 设计要求应具备检测口令的长度和是否在指定字符集合内的能力。应具备检测口令字符逻辑相邻的能力,如aBc,abC等。
- mybatis的环境搭建:1、创建maven工程并且导入坐标:即我们需要在pop.xml文件中添加我们需要的依赖具体方法:搜索maven中央
- 概述关于 static 关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的。也就是说,既
- Java异常简介Java异常是Java提供的一种识别及响应错误的一致性机制。Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证
- Android 切圆图效果图如下:MyView 类public class MyView extends View {Bitmap bmp;
- 一. 思路今天接到个小任务,让把json文件转换成excel文件,按照列展开.思路:既然json已经都已经是现成的,那直接将jso
- 前言一直很好奇Android Root的原理,恰好最近碰到了一个跟Android默认带Root权限的问题,这里顺便记录一下Android系统
- 一、引言在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,
- Mybatis-Plus是一个优秀的Mybatis增强工具,目前更新到3.1.1。Mybatis-Plus原生提供了很多单表操作的方法,极大
- 本文实例为大家分享了Android实现点击获取验证码60秒后重新获取的具体代码,供大家参考,具体内容如下上代码/** * Created b
- 1、概述本文通过手动实现迭代器来了解foreach语句的本质。2、使用foreach语句遍历集合在C#中,使用foreach语句来遍历集合。
- 在观察者模式中有2个要素:一个是被观察对象,另一个是观察者。但被观察对象的状态发生改变会通知观察者。举例:把订阅报纸的人看作是观察者,把报纸
- Android深入浅出之Binder机制一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Se