合并排序

归并排序的分析与Java实现

邮差的信 提交于 2019-12-28 04:06:39
归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。 归并排序算法依赖归并操作。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 归并排序在众多排序算法中既是稳定排序,效率也比较高,同时,归并排序不仅可以用于内排序,还可以用于外排序。 1.两个有序数列的合并 设两个有序数列放在同一向量中相邻的位置上:R[low..m],R[m+1..high],先将它们合并到一个局部的暂存向量 R1中,待合并完成后将 R1 复制回 R[low..high]中。 (1)合并过程 合并过程中,设置 i,j 和 p 三个指针,其初值分别指向这三个记录区的起始位置。 合并时依次比较 R[i]和 R[j]的关键字,取关键字较小的记录复制到 R1[p]中,然后将被复制记录的指针 i 或 j 加 1,以及指向复制位置的指针 p 加 1。 重复这一过程直至两个输入的子文件有一个已全部复制完毕,此时将另一非空的子文件中剩余记录依次复制到 R1 中即可。 (2)动态申请 R1 实现时,R1 是动态申请的,因为申请的空间可能很大,所以在工程上应用时,可能需要加入申请空间是否成功的处理。 2.归并排序的实现 (1)二路归并的思路 将数组划均分为两个子数组; 对两个字数组进行排序; 将排序好的两个字数组归并。 所谓 N路归并 是指将数组均分为N个子数组

归并排序就这么简单

旧街凉风 提交于 2019-12-28 04:05:47
归并排序就这么简单 从前面已经讲解了冒泡排序、选择排序、插入排序,快速排序了,本章主要讲解的是 归并排序 ,希望大家看完能够理解并手写出归并排序快速排序的代码,然后就通过面试了!如果我写得有错误的地方也请大家在评论下指出。 归并排序的介绍 来源百度百科: 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法 (Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。 若将两个有序表合并成一个有序表,称为二路归并。 过程描述: 归并过程为:比较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]。 原理: 归并操作的工作原理如下: 第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 第二步:设定两个指针

重读算法导论之算法基础

本小妞迷上赌 提交于 2019-12-27 14:51:32
重读算法导论之算法基础 插入排序 ​ 对于少量数据的一种有效算法。原理: 整个过程中将数组中的元素分为两部分,已排序部分A和未排序部分B 插入过程中,从未排序部分B取一个值插入已排序的部分A 插入的过程采用的方式为: 依次从A中下标最大的元素开始和B中取出的元素进行对比,如果此时该元素与B中取出来的元素大小关系与期望不符,则将A中元素依次向右移动 ​ 具体代码如下: public static void insertionSort(int[] arr) { // 数组为空或者只有一个元素的时候不需要排序 if (arr == null || arr.length <= 1) { return; } // 开始插入排序,先假设元素组第一个元素属于已经排好序的A部分,依次从B部分取出元素,进行比较插入 for (int j = 1; j < arr.length; j++) { int key = arr[j]; int i = j - 1; for (; i >= 0; i--) { if (arr[i] > key) { arr[i + 1] = arr[i]; } else { break; } } arr[i+1] = key; } } ​ 易错点为,最后应该是设置arr[i + 1] = key。 可以设想假设A中所有元素都比B中选出来的数小的时候

Contest100000586 - 《算法笔记》4.6小节——算法初步->two pointers

大憨熊 提交于 2019-12-27 00:43:45
常用模板 two pointers:利用问题本身与序列的特性,使用两个下标 i,j 对序列进行扫描(可以同向扫描,也可以反向扫描),以较低的复杂度(一般是 O ( n ) O(n) O ( n ) )解决问题。 定和问题 给定一个 递增 的 正整数序列 和一个正整数M,求序列中的两个 不同位置 的数a和b,使得它们的和恰好为M,输出 所有 满足条件的方案。 模板如下: while ( i < j ) { if ( a [ i ] + a [ j ] == m ) { cout << i << ' ' << j ; ++ i ; -- j ; } else if ( a [ i ] + a [ j ] < m ) ++ i ; else -- j ; } 由于 i 的初值为0,j 的初值为n - 1(i,j 分别指向序列的第一个和最后一个元素),而 i 只递增,j 只递减,循环当 i >= j 时停止,因此 i 和 j 的操作最多为n次。即时间复杂度为 O ( n ) O(n) O ( n ) 。 序列合并问题 假设有两个递增序列A与B,要求将它们合并为一个递增序列C。设置两个下标 i 和 j,初值均为0,分别指向序列A和序列B的第一个元素。 int Merge ( int A [ ] , int B [ ] , int C [ ] , int n , int m ) { int i

23. 【困难】合并K个排序链表

删除回忆录丶 提交于 2019-12-22 13:54:53
23. 合并K个排序链表 题目描述 思路 代码 链接 题目描述 思路 可以用 循环 或者 递归 的方式处理 合并两个有序链表 对于合并K个有序链表,可以采用 分治 的思想 如果链表数组中,左半部分合并好了,右半部分合并好了,我们只需合并两个有序链表即可完成任务 代码 /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode mergeKLists ( ListNode [ ] lists ) { if ( lists == null || lists . length == 0 ) { return null ; } if ( lists . length == 1 ) { return lists [ 0 ] ; } int mid = lists . length / 2 ; ListNode [ ] l1 = new ListNode [ mid ] ; ListNode [ ] l2 = new ListNode [ lists . length - mid ] ; for ( int i = 0 ; i

LeetCode:合并K个排序链表

风流意气都作罢 提交于 2019-12-11 00:54:32
题目: 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 我的答案: 解法一:暴力法 /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode mergeKLists(ListNode[] lists) { //ListNode node = new ListNode(0); if(lists==null||lists.length==0){ return null; } //node.next = lists.get(0); ListNode temp = lists[0]; for(int i=1;i<lists.length;i++){ temp = mergeTwoLists(temp,lists[i]); } return temp; } public ListNode mergeTwoLists(ListNode l1,ListNode l2){

数据结构与算法-归并排序

懵懂的女人 提交于 2019-12-06 02:18:25
原理: 分解过程 : 存在序列A[1...n],将这个序列分解成俩个序列(↓(n/2)向下取整为m),一边含m个数元素序列A[1...m],一边n-m个数元素序列A[m+1...n]; 合并过程 : 针对俩个序列A的俩个子序列A[p...q],A[q+1...s],而且A[p...q],A[q+1...s]都是各自排序好的序列,现在合并得到一个A[p...s]排序好的子序列; 停止分解 : 序列中只有一个元素时,那么这个序列就是有序序列,可以停止分解过程; 归并排序 : 递归分解、合并过程(递归结束判断就是序列中元素只有一个); 合并过程的伪代码: 合并序列A的俩个子序列A[p...q],A[q+1...s]且都是已经排序好的子序列 设置∞为元素的最大值 MERGE(A , p , q , s) { // 为了方便表示给A[p...q],A[q+1...s]赋值L和R序列 L[1...q-p+1] = A[p,q]; R[1...s-q]= A[q+1,s] ; // 分别给L和R序列设置一个最大值 L[q-p] = ∞; R[s+1] = ∞; // 定义俩个变量存储L和R中元素的位置 i = 1; j = 1; for(k = p; k<= s; k++) { if(L[i] <= R[j]){ A[k] = L[i] i++; } else { A[k] = R[j]; j+

必学十大经典排序算法,看这篇就够了(附完整代码/动图/优质文章)

送分小仙女□ 提交于 2019-12-05 07:44:00
原创:微信公众号 帅地 苦逼的码农 说明 十大排序算法 可以说是每个程序员都必须得掌握的了,花了一天的时间把代码实现且整理了一下,为了方便大家学习,我把它整理成一篇文章,每种算法会有简单的 算法思想描述 ,为了方便大家理解,我还找来了 动图演示 ;这还不够,我还附上了对应的 优质文章。 术语铺垫 有些人可能不知道什么是稳定排序、原地排序、时间复杂度、空间复杂度,我这里先简单解释一下: 1、稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。 2、非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。 3、原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。 4、非原地排序:需要利用额外的数组来辅助排序。 5、时间复杂度:一个算法执行所消耗的时间。 6、空间复杂度:运行完一个算法所需的内存大小。 另: 代码说明: 代码我自己写的,并且都是经过好几组数据测试通过,应该没啥问题,如有错,还请反馈下,谢谢。 图片说明: 图片和动画都是在百度搜索的,如有侵权,还望联系我删除,谢谢 1、选择排序 过程简单描述: 首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置

Java排序算法总结(转载)

流过昼夜 提交于 2019-12-04 20:14:29
文件源于 : https://www.cnblogs.com/Jason-Xiang/p/8567751.html 排序算法 平均时间复杂度 冒泡排序 O(n2) 选择排序 O(n2) 插入排序 O(n2) 希尔排序 O(n1.5) 快速排序 O(N*logN) 归并排序 O(N*logN) 堆排序 O(N*logN) 基数排序 O(d(n+r)) 一. 冒泡排序(BubbleSort) 基本思想: 两个数比较大小,较大的数下沉,较小的数冒起来。 过程: 比较相邻的两个数据,如果第二个数小,就交换位置。 从后向前两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了。 继续重复上述过程,依次将第2.3...n-1个最小数排好位置。 平均时间复杂度: O(n2) java代码实现: public static void BubbleSort(int [] arr){ int temp;//临时变量 for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。 for(int j=arr.length-1; j>i; j--){ if(arr[j] < arr[j-1]){ temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } } } }

基于合并排序的分治法求逆序数(python)

南笙酒味 提交于 2019-12-04 19:19:00
1 #先看看合并排序 2 def merge(A,B): 3 lenA,lenB=len(A),len(B) 4 i,j=0,0 5 C=[] 6 while(i<lenA and j<lenB): 7 if A[i]<B[j]: 8 C.append(A[i]) 9 i+=1 10 else: 11 C.append(B[j]) 12 j+=1 13 if i<lenA: 14 C=C+A[i:] 15 if j<lenB: 16 C=C+B[j:] 17 return C 18 19 20 def merge_sort(L): 21 if len(L)==1: 22 return L 23 else: 24 A=merge_sort(L[0:len(L)//2]) 25 B=merge_sort(L[len(L)//2:]) 26 return merge(A,B) 27 28 #以下是求逆序 29 30 def merge_count(A,B): 31 #merge和数逆序同时 32 lenA,lenB=len(A),len(B) 33 i,j,rC=0,0,0 34 C=[] 35 while(i<lenA and j<lenB): 36 if A[i]>B[j]: 37 C.append(B[j]) 38 j+=1 39 rC+=lenA-i 40 else: 41 C