归并排序

归并排序(Merge sort)

本小妞迷上赌 提交于 2019-12-01 00:15:02
定义 归并排序采用分治策略进行比较操作排序,将待排序的n个元素分解为个含n/2个元素的两部分,使用递归或其它方式迭代地两个子序列进行同样的排序操作,然后合并两个已排序的子序列。 分析 序列的划分 序列的划分较为简单直接,n为奇数时两部分长度相差1,可以规定将较长的一部分作为第二部分的长度。 序列的合并 从最基本的合并开始,如果划分到一个子序列仅有一个元素时,不能进一步划分,对该子序列的归并排序会直接返回,对应于n=1时的归并排序,是直接求解的不需要进行归并操作。当单元素子序列归并排序完成时,将两个子序列进行合并得到两个元素的子序列,对应于n=2时的归并排序就完成了,以此类推,不失一般性考虑如何合并任意大小的两个已排序子序列的问题。 对于序列的划分操作需要进行*lg*n次,每次都需要对n个元素进行合并操作,而合并本身也是对两个有序子序列的再排序,合并的开销必须尽可能地小,至少需要将所有子序列遍历一遍,其渐进复杂度下界是Ω(n)。如果采用原址排序的方式,由于两个子序列除了自身是有序的,两者之间没有任何联系,这会是一个一般性的排序问题。因此,为了利用已排序的子序列,将两者复制后依次进行比较并合并回原序列中。 实现 def merge_sort(A, start, end): if end - start <= 1: return mid = (end + start) / 2 merge

归并排序(Merge sort)

浪尽此生 提交于 2019-12-01 00:06:55
定义 归并排序采用分治策略进行比较操作排序,将待排序的n个元素分解为个含n/2个元素的两部分,使用递归或其它方式迭代地两个子序列进行同样的排序操作,然后合并两个已排序的子序列。 分析 序列的划分 序列的划分较为简单直接,n为奇数时两部分长度相差1,可以规定将较长的一部分作为第二部分的长度。 序列的合并 从最基本的合并开始,如果划分到一个子序列仅有一个元素时,不能进一步划分,对该子序列的归并排序会直接返回,对应于n=1时的归并排序,是直接求解的不需要进行归并操作。当单元素子序列归并排序完成时,将两个子序列进行合并得到两个元素的子序列,对应于n=2时的归并排序就完成了,以此类推,不失一般性考虑如何合并任意大小的两个已排序子序列的问题。 对于序列的划分操作需要进行*lg*n次,每次都需要对n个元素进行合并操作,而合并本身也是对两个有序子序列的再排序,合并的开销必须尽可能地小,至少需要将所有子序列遍历一遍,其渐进复杂度下界是Ω(n)。如果采用原址排序的方式,由于两个子序列除了自身是有序的,两者之间没有任何联系,这会是一个一般性的排序问题。因此,为了利用已排序的子序列,将两者复制后依次进行比较并合并回原序列中。 实现 def merge_sort(A, start, end): if end - start <= 1: return mid = (end + start) / 2 merge

排序算法(第三弹)归并排序和基数(桶)排序

耗尽温柔 提交于 2019-11-30 15:08:50
归并排序 排序动图演示 整体效果: 排序细节: 排序原理: 归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序 1. 向上归并排序的时候,需要一个暂存数组用来排序, 2. 将待合并的两个数组,从第一位开始比较,小的放到暂存数组,指针向后移, 3. 直到一个数组空,这时,不用判断哪个数组空了,直接将两个数组剩下的元素追加到暂存数组里, 4. 再将暂存数组排序后的元素放到原数组里,两个数组合成一个,这一趟结束。 我的代码实现: 1 package cn.ftf.mysort; 2 3 import java.util.Arrays; 4 5 public class MyMergeSort { 6 //完善参数,外部调用 7 public static int[] mergeSort(int[] arr) { 8 int [] temp=new int[arr.length]; 9 arr=mergeSort1(arr,0,arr.length-1,temp); 10 return arr; 11 } 12 //分+治 13 private static int[] mergeSort1(int[] arr,int left,int right,int[] temp) { 14 if(left<right) { 15 int mid

深圳哪里有卖银行卡

守給你的承諾、 提交于 2019-11-30 13:35:08
深圳哪里有卖银行卡█ █微信:619998462█ █ LevelDB是一个可持久化的KV数据库引擎,由Google传奇工程师Jeff Dean和Sanjay Ghemawat开发并开源。无论从设计还是代码上都可以用精致优雅来形容,非常值得细细品味。本文将从整体特性、架构和使用等几方面做一个解释,试图通过本文的介绍让大家对LevelDB有个整体的认识并能够使用。 设计思路 做存储的同学都很清楚,对于普通机械磁盘顺序写的性能要比随机写大很多。比如对于15000转的SAS盘,4K写IO, 顺序写在200MB/s左右,而随机写性能可能只有1MB/s左右。而LevelDB的设计思想正是利用了磁盘的这个特性。 LevelDB的数据是存储在磁盘上的,采用LSM-Tree的结构实现。LSM-Tree将磁盘的随机写转化为顺序写,从而大大提高了写速度。为了做到这一点LSM-Tree的思路是将索引树结构拆成一大一小两颗树,较小的一个常驻内存,较大的一个持久化到磁盘,他们共同维护一个有序的key空间。写入操作会首先操作内存中的树,随着内存中树的不断变大,会触发与磁盘中树的归并操作,而归并操作本身仅有顺序写。如下图所示: 图1 数据存储原理 图中2个红色区域是要进行归并的数据块,计算出顺序后会存储到如图下面的磁盘空间,而这种存储方式是追加式的,也就是顺序写入磁盘。 随着数据的不断写入

广州哪里有卖银行卡

北城余情 提交于 2019-11-30 13:35:00
广州哪里有卖银行卡█ █微信:619998462█ █ LevelDB是一个可持久化的KV数据库引擎,由Google传奇工程师Jeff Dean和Sanjay Ghemawat开发并开源。无论从设计还是代码上都可以用精致优雅来形容,非常值得细细品味。本文将从整体特性、架构和使用等几方面做一个解释,试图通过本文的介绍让大家对LevelDB有个整体的认识并能够使用。 设计思路 做存储的同学都很清楚,对于普通机械磁盘顺序写的性能要比随机写大很多。比如对于15000转的SAS盘,4K写IO, 顺序写在200MB/s左右,而随机写性能可能只有1MB/s左右。而LevelDB的设计思想正是利用了磁盘的这个特性。 LevelDB的数据是存储在磁盘上的,采用LSM-Tree的结构实现。LSM-Tree将磁盘的随机写转化为顺序写,从而大大提高了写速度。为了做到这一点LSM-Tree的思路是将索引树结构拆成一大一小两颗树,较小的一个常驻内存,较大的一个持久化到磁盘,他们共同维护一个有序的key空间。写入操作会首先操作内存中的树,随着内存中树的不断变大,会触发与磁盘中树的归并操作,而归并操作本身仅有顺序写。如下图所示: 图1 数据存储原理 图中2个红色区域是要进行归并的数据块,计算出顺序后会存储到如图下面的磁盘空间,而这种存储方式是追加式的,也就是顺序写入磁盘。 随着数据的不断写入

厦门哪里有卖银行卡

旧城冷巷雨未停 提交于 2019-11-30 13:34:52
厦门哪里有卖银行卡█ █微信:619998462█ █ LevelDB是一个可持久化的KV数据库引擎,由Google传奇工程师Jeff Dean和Sanjay Ghemawat开发并开源。无论从设计还是代码上都可以用精致优雅来形容,非常值得细细品味。本文将从整体特性、架构和使用等几方面做一个解释,试图通过本文的介绍让大家对LevelDB有个整体的认识并能够使用。 设计思路 做存储的同学都很清楚,对于普通机械磁盘顺序写的性能要比随机写大很多。比如对于15000转的SAS盘,4K写IO, 顺序写在200MB/s左右,而随机写性能可能只有1MB/s左右。而LevelDB的设计思想正是利用了磁盘的这个特性。 LevelDB的数据是存储在磁盘上的,采用LSM-Tree的结构实现。LSM-Tree将磁盘的随机写转化为顺序写,从而大大提高了写速度。为了做到这一点LSM-Tree的思路是将索引树结构拆成一大一小两颗树,较小的一个常驻内存,较大的一个持久化到磁盘,他们共同维护一个有序的key空间。写入操作会首先操作内存中的树,随着内存中树的不断变大,会触发与磁盘中树的归并操作,而归并操作本身仅有顺序写。如下图所示: 图1 数据存储原理 图中2个红色区域是要进行归并的数据块,计算出顺序后会存储到如图下面的磁盘空间,而这种存储方式是追加式的,也就是顺序写入磁盘。 随着数据的不断写入

LevelDB深入浅出之整体架构

被刻印的时光 ゝ 提交于 2019-11-30 12:55:07
LevelDB是一个可持久化的KV数据库引擎,由Google传奇工程师Jeff Dean和Sanjay Ghemawat开发并开源。无论从设计还是代码上都可以用精致优雅来形容,非常值得细细品味。本文将从整体特性、架构和使用等几方面做一个解释,试图通过本文的介绍让大家对LevelDB有个整体的认识并能够使用。 设计思路 做存储的同学都很清楚,对于普通机械磁盘顺序写的性能要比随机写大很多。比如对于15000转的SAS盘,4K写IO, 顺序写在200MB/s左右,而随机写性能可能只有1MB/s左右。而LevelDB的设计思想正是利用了磁盘的这个特性。 LevelDB的数据是存储在磁盘上的,采用LSM-Tree的结构实现。LSM-Tree将磁盘的随机写转化为顺序写,从而大大提高了写速度。为了做到这一点LSM-Tree的思路是将索引树结构拆成一大一小两颗树,较小的一个常驻内存,较大的一个持久化到磁盘,他们共同维护一个有序的key空间。写入操作会首先操作内存中的树,随着内存中树的不断变大,会触发与磁盘中树的归并操作,而归并操作本身仅有顺序写。如下图所示: 图1 数据存储原理 图中2个红色区域是要进行归并的数据块,计算出顺序后会存储到如图下面的磁盘空间,而这种存储方式是追加式的,也就是顺序写入磁盘。 随着数据的不断写入,磁盘中的树会不断膨胀,为了避免每次参与归并操作的数据量过大

逆序对

不羁岁月 提交于 2019-11-30 12:51:27
今天想写一个专题:如何求一串数中的逆序对个数。 具体来讲,一共有两种比较好的方法: 归并排序 树状数组 两种方法的比较 先来比较一下两个方法: 方法 时间复杂度 空间复杂度 代码长度 理解难度 归并排序 相比较长 (除非你用STL) 容易 树状数组 短小精悍 (用不到STL) 一般 好吧,其实并没有多大区别,但是还是建议这两个方法都学一下 归并排序 其实就是在归并排序的时候发现一个较大的数在前面,计算一个逆序对个数,废话不多说,直接看代码理解吧。 代码 void Msort(int l,int r) { int ret[500002]; if(l!=r) { int mid=(l+r)/2; Msort(l,mid);Msort(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { if(a[i].num<=a[j].num) { ret[k]=a[i].num; i++;k++; }else { ret[k]=a[j].num; j++;k++;ans=(ans+mid-i+1)%P;//加上逆序对个数(模P) }; }; while(i<=mid) { ret[k]=a[i].num; i++;k++; }; while(j<=r) { ret[k]=a[j].num; j++;k++; }; for(int i=l;i<=r

数据库中间件 Sharding-JDBC 源码分析 —— 结果归并

妖精的绣舞 提交于 2019-11-30 05:57:49
摘要: 原创出处 http://www.iocoder.cn/Sharding-JDBC/result-merger/ 「芋道源码」欢迎转载,保留摘要,谢谢! 本文主要基于 Sharding-JDBC 1.5.0 正式版 1. 概述 2. MergeEngine 2.1 SelectStatement#setIndexForItems() 2.2 ResultSetMerger 2.2.1 AbstractStreamResultSetMerger 2.2.2 AbstractMemoryResultSetMerger 2.2.3 AbstractDecoratorResultSetMerger 3. OrderByStreamResultSetMerger 3.1 归并算法 3.2 #next() 4. GroupByStreamResultSetMerger 4.1 AggregationUnit 4.2 #next() 5. GroupByMemoryResultSetMerger 5.1 #next() 6. IteratorStreamResultSetMerger 7. LimitDecoratorResultSetMerger 666. 彩蛋 ������关注 微信公众号:【芋道源码】 有福利: 1. RocketMQ / MyCAT / Sharding-JDBC

面试官:手写一个归并排序,并对其改进

◇◆丶佛笑我妖孽 提交于 2019-11-30 00:57:21
之前曾介绍过快排、冒泡、插入等排序算法,这篇文章介绍一下归并排序。也算是一个比较有名的排序算法。 一、排序原理 归并排序的思想很简单,如果有一组待排序列,先切分再重组。任何一篇教程也都会说采用的是分治法,意思就是这么个意思,再细致一点的理解就是: 将一组待排序,先分割成一个一个的元素,然后将这些元素先两两排序,再四四排序,八八排序,一直到排序完所有的元素。 也就是说归并排序其实就是将 已有序的子序列合并 ,得到完全有序的序列。我们看一张动图来认识一下: 是不是有点理解了,动态图的作用其实就是为了方便你了解整个归并过程,不理解也没关系,我们再来看一张静态图,帮助你从细节上来理解。 上面的这张图基本上能把整个归并排序的流程了解清楚了。也就是文章开头提到的先切分再重组。下面我们使用代码来实现一下归并排序,并对其做一个改进: 二、代码实现 1、基本实现 基本实现的思想很简单,我们就是先切分成一个个元素,然后再合并就好了。 //data:表示待排序列 //left:表示当前序列的左边界 //right:表示当前序列的右边界 public static void sort ( int [ ] data , int left , int right ) { if ( left >= right ) return ; // 找出中间索引 int center = ( left + right )