归并排序

归并排序代码实现

一个人想着一个人 提交于 2019-11-27 16:02:39
描述: 归并排序 - 外部排序(内存有限制,数据无法一次性放入内存,怎么对数据进行排序) JDK库里面的Java代码,涉及排序都优先采用快排(空间复杂度更好一点) 外部排序的问题(文件的操作): 现在有50亿个整数,内存限制200M,问你该怎么对这 50亿个整数进行排序? 50亿 = 5G * 4 = 20G 步骤一:先生成100个小文件,每个文件保存一部分数据 大文件里面的整数 % 100 = 小文件的下标 一亿个整数的文件, 内存限制4M 100M * 4 = 400M 1G = 10亿 100M = 1亿 package sort; import java.util.Arrays; import java.util.Collections; public class MergeSort { public static void main(String[] args) { int[] arr = new int[20]; for (int i = 0; i < arr.length; i++) { arr[i] = (int)(Math.random()*100); } mergeSort(arr, 0, arr.length-1); System.out.println(Arrays.toString(arr)); } /** * 实现归并排序 * @param arr *

归并排序

江枫思渺然 提交于 2019-11-27 15:22:44
1、什么是归并排序?   归并排序是属于分冶法的一种排序方式,归并排序将待排序的元素序列分成两个长度相等的子序列,为每一个子序列排序,然后再将他们合并成一个子序列。合并两个子序列的过程也就是两路归并。 2、时间复杂度和空间复杂度   归并排序是一种稳定的排序算法,一般用于对总体无序,但是各子项相对有序的数列。   归并排序的主要问题在于它需要一个与待排序数组一样大的辅助数组空间,所以空间复杂度为T(n)。   由于归并排序每次划分时两个子序列的长度基本一样,所以归并排序最好、最差和平均时间复杂度都是(nlogn)。 3、算法描述   将原本的待排序的数列不断的分解为两个子序列,直到子序列长度为1时开始合并   利用递归的方式分解数列   创建一个和原数组待排序字段长度一致的新数组,分别遍历字段的前半部分和后半部分取值,取其中较小的值   直到一部分遍历结束,将另一部分剩余的值全部赋予新数组   将新数组复制到原数组的待排序字段 4、java代码实现 public class Test { public static void main(String[] args) { // TODO Auto-generated method stub int[] A = {5,2,4,5,6,2,3,6,7,9}; sort(A,1,9);//第一个5不参加排序 for(int l=0;l<A

排序算法----归并排序

你。 提交于 2019-11-27 14:15:09
归并排序   归并排序采用分而治之的原理:     - 将一个序列从中间位置分成两个序列;     - 在将这两个子序列按照第一步继续二分下去;     - 直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。   下图中的倒数第三行表示为第一次合并后的数据。其中一组数据为 4 8 , 5 7。该两组数据合并方式为:每一小组数据中指定一个指针,指针指向每小组数据的第一个元素,通过指针的偏移指定数据进行有序排列。排列情况如下:       1. p1指向4,p2指向5,p1和p2指向的元素4和5进行比较,较小的数据归并到一个新的列表中。经过比较p1指向的4会被添加到新的列表中,则p1向后偏移一位,指向了8,p2不变。       2.p1和p2指向的元素8,5继续比较,则p2指向的5较小,添加到新列表中,p2向后偏移一位,指向了7。       3.p1和p2指向的元素8,7继续比较,7添加到新列表中,p2偏移指向NULL,比较结束。       4.最后剩下的指针指向的数据(包含该指针指向数据后面所有的数据)直接添加到新列表中即可。       1 def merge_sort(alist): 2 n = len(alist) 3 #结束递归的条件 4 if n <= 1: 5 return alist 6 #中间索引 7 mid = n//2

排序算法--归并排序

风格不统一 提交于 2019-11-27 14:15:06
这次备忘一下归并排序。归并排序是分治方法的典型应用。 步骤 :1、把序列分成元素个数尽量相等的两半 2、把两半元素分别排序 3、把两个有续表合并 其中,分治使用的是递归,出口就是被分到的组元素个数小于等于1 分析 :先看时间复杂度,涉及二分的,一般就是O(nlogn)。稳定性方面,相等元素被分到二个组中,合并的时候并不会出现顺序颠倒,所以是稳定的。空间复杂度方面,需要一个临时存储数组,为O(N). 代码展示 : public class MergSort { public static void main(String[] args){ int[] target = {1,10,2,5,7,3,5,8}; int[] tmp = new int[target.length];//建一个临时存储数组 new MergSort().merg_sort(target, 0, target.length, tmp); System.out.print("Result:"+" "); for(int k : target) System.out.print(k+" "); } public void merg_sort(int[] target,int x,int y,int[] tmp){ if(y-x>1){//程序传进来的y是需要排序数组段最后一个元素的下一个元素下标 int m =

归并排序

浪子不回头ぞ 提交于 2019-11-27 13:16:46
def MergeSort(array): arrayLen = len(array) # 先判断边界条件 if arrayLen<1: return [] if arrayLen == 1: return array #做map操作,也就是divide index = arrayLen//2 arrayleft = MergeSort(array[:index]) arrayright = MergeSort(array[index:]) retarray = MergeCore(arrayleft,arrayright) return retarray def MergeCore(arrayleft,arrayright): # 先判断边界条件 if len(arrayleft)==0: return arrayright if len(arrayright)==0: return arrayleft # 定义2个指针,分别指向两个有序数组的第一个元素 i,j = 0,0 retarray = [] while i < len(arrayleft) and j < len(arrayright): if arrayleft[i]<arrayright[j]: retarray.append(arrayleft[i]) i += 1 else: retarray.append

归并排序

眉间皱痕 提交于 2019-11-27 12:04:02
推荐一个网站 https://visualgo.net/zh 这个网站可以看到很多算法的动态演绎 大概就是这个亚子,可以自己去看归并排序 下边给出归并排序的代码 1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 const int maxn=501000; 6 ll n,m,i,j,k,a[maxn],b[maxn],cnt; 7 8 void mergesort(ll a[],ll l,ll r) 9 { 10 if (r-l<1) return ; 11 ll mid=(l+r)>>1; 12 mergesort(a,l,mid); 13 mergesort(a,mid+1,r); 14 ll i=l,j=mid+1; // i是第一段序列的下标, j是第二段序列的下标 15 for (ll k=l;k<=r;k++){ 16 if (j>r || (i<=mid && a[i]<=a[j])) // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描 17 b[k]=a[i++]; 18 else{ 19 b[k]=a[j++]; 20 } 21 } 22 for (ll k=l;k<=r;k++) 23 a[k]=b[k]; 24 } 25 26 int

排序算法 - 归并排序

故事扮演 提交于 2019-11-27 11:02:07
基本思路 归并排序的基本思想是:首先将a[0..n-1]看成是n个长度为1的有序表,将相邻的k(k≥2)个有序子表成对归并,得到n/k个长度为k的有序子表;然后再将这些有序子表继续归并,得到n/k2个长度为k2的有序子表,如此反复进行下去,最后得到一个长度为n的有序表。 若k=2,即归并在相邻的两个有序子表中进行的,称为二路归并排序。若k>2,即归并操作在相邻的多个有序子表中进行,则叫多路归并排序。 例如 : 对于{2,5,1,7,10,6,9,4,3,8}序列,其自底向上的排序过程如下图所示,图中方括号内是一个有序子序列。   循环log2n次,length依次取1、2、…、log2n。每次执行以下步骤:   ① 分解:将原序列分解成length长度的若干子序列。   ② 求解子问题:将相邻的两个子序列调用Merge算法合并成一个有序子序列。   ③ 合并:由于整个序列存放在数组中a中,排序过程是就地进行的,合并步骤不需要执行任何操作。 自顶向下的排序过程如下图所示   ① 分解:将序列a[low..high]一分为二,即求mid=(low+high)/2;递归地对两个子序列a[low..mid]和a[mid+1..high]进行继续分解。其终结条件是子序列长度为1(因为一个元素的子表一定是有序表)。   ② 合并:与分解过程相反,将已排序的两个子序列a[low..mid]和a

JavaScript实现归并排序

徘徊边缘 提交于 2019-11-27 09:46:22
JavaScript实现归并排序 参考文章 归并排序就这么简单 ---文章通俗易懂,加深理解 过程描述 归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。 代码实现 根据参考文章,仅做语言上的修改变更,后文有代码简化版 /** * 归并排序 * @param {Array} arrays * @param {Number} L 数组第一个元素 * @param {Number} R 数组最后一个元素 */ function mergeSort(arrays, l, r) { if (l === r) { return; } else { // 取中间的数,进行拆分 const m = Math.floor((l + r) / 2); //左边不断进行拆分 mergeSort(arrays, l, m); //右边不断进行拆分 mergeSort

归并排序

若如初见. 提交于 2019-11-27 08:37:05
没有几个写归并排序的dalao? 我翻了好几页,就看到一位dalao写了归并排序,而且没有任何说明和注释 ,也有可能是我眼睛不好使,望各位dalao和管理见谅 本来要写逆序对这个题,然后来这里先联系一下归 龟 排 归并排序利用的是分治思想 假如有两个已经排好序的序列,你怎么合并他们? 举个例子吧,我们搞两个指针l和r,初始时令他们=各自序列第一个数的位置 1 4 10 2 11 15 那么a[l] 就等于1,a[r]就等于2 (1)首先a[l] < a[r] 我们将a[l]加入另一个待选数列t[] = {1}; 然后l++ (2)现在a[l] > a[r] 把a[r]加入t[] = {1,2} 然后r++ (3)然后a[l] < a[r] a[l] 加入t[] = {1,2,4} l++ (4)a[l] < a[r] a[l] 加入t[] = {1,2,4,10} ,然后l++ 我们现在发现l > 第一个数组的长度,代表第一个数组的最大值也不如a[r] 及a[r]之后的数大,所以把剩下数全加进去 最终t[] = {1,2,4,10,11,15} 那么我们怎么得到两个有序的数列呢? 我们发现,如果一个数列只有一个数,那么它是有序的,这样我们就可以递归解决问题,递归到1就返回,因为已经排好了 以上就是龟排的过程 #include<bits/stdc++.h> //万能头 using

PAT 1035 插入与归并 C语言实现

邮差的信 提交于 2019-11-27 08:22:10
根据维基百科的定义: 插入排序 是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。 归并排序 进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。 现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法? 输入格式: 输入在第一行给出正整数 N (≤100);随后一行给出原始序列的 N 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。 输出格式: 首先在第 1 行中输出 Insertion Sort 表示插入排序、或 Merge Sort 表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。 输入样例 1: 10 3 1 2 8 7 5 9 4 6 0 1 2 3 7 8 5 9 4 6 0 输出样例 1: Insertion Sort 1 2 3 5 7 8 9 4 6 0 输入样例 2: 10 3 1 2 8 7 5 9 4 0 6 1 3 2 8 5 7 4 9 0 6 输出样例 2: Merge Sort 1 2 3 8