合并排序

三个较为高效的排序算法

我的梦境 提交于 2019-12-01 14:44:44
以下三个排序算法平均时间复杂度均为 堆排序(Heap Sort) 不稳定排序,接下来引入几个概念: 堆 一个如此编号的完全二叉树(完全二叉树:对于树中任意一个非叶节点,它要么左右子节点都有,要么只有左子节点。) 对于每个节点,其左子节点编号为其2倍,右子节点为2倍加1。 最大堆 父节点存的数永远比左右子节点存的数都大,如图: 同理,最小堆即:父节点存的数永远比左右子节点存的数都小。 排序步骤 以最大堆为例,也就是降序排序。 首先要构建最大堆: 1.每读入一个数,每个数放置在堆的对应位置(就是它的数组下标)。 2.然而对于这个数,与其父节点比较,大于就交换,越界或交换不了就退出。(相当于把这个数一层层往上提,直到提不动或越界) 3.重复1、2步骤,直到所有数据读入。 其次要维护最大堆: 1.将根节点(a[1])存储的数输出。(因为它一定是整个堆中最大的) 2.将堆末(即a[n])的数移至根节点,同时n--。 3.维护最大堆:将根节点的数与子节点比较,若左右子节点中有比它大的,则与左右子节点中较大的交换,直到无法交换或越界。(相当于把这个数一层层往下拉,直到拉不动或越界) 4.重复1、2、3步骤,直到所有数输出。 代码如下 #include <stdio.h> #include <iostream> #include <algorithm> using namespace std;

16.分治排序

你说的曾经没有我的故事 提交于 2019-12-01 08:01:49
分阶段可以理解为就是递归拆分子序列的过程 治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8] import java.util.Arrays; /** * 归并排序 */ public class MergeSort { public static void mergeSort(int[] arr,int left,int right,int[] temp){ if (left<right){ int mid = (left+right)/2; //前一部分分解 mergeSort(arr,left,mid,temp); //后一部分分解 mergeSort(arr,mid+1,right,temp); //合并 merge(arr,left,mid,right,temp); } } /** * 合并 如 4,5,7,8, 1,2,3,6 * @param arr 原始数组 由两部分组成 * @param left 数组的第一个索引 * @param mid 数组前一部分最后一个元素的索引 * @param right 数组的最后一个索引 * @param temp 临时数组 */ public static void merge(int

数据库中间件 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

23. 合并K个排序链表

烂漫一生 提交于 2019-11-28 04:51:16
/** * 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.length==0) return null; Queue<ListNode> pq=new PriorityQueue(lists.length,new Comparator<ListNode>() { @Override public int compare(ListNode o1,ListNode o2) { return o1.val-o2.val; } }); ListNode root=new ListNode(0); for(int i=0;i<lists.length;i++) if(lists[i]!=null) pq.add(lists[i]); ListNode p=root; while(!pq.isEmpty()) { ListNode q=pq.remove(); p.next=q; p=p.next; if(q.next!=null

归并排序

回眸只為那壹抹淺笑 提交于 2019-11-28 00:44:40
算法思想 归并排序使用了分治的套路,先将待排序元素划分为个数均等的两部分,然后在对已经划分的两个部分在进行均等 划分,如此递归的划分下去,直到区间无法在划分时停止,然后合并这些子区间即可;合并时每次从两个子区间内选 出最大(降序排序)或者最小(升序排序)的元素放入辅助空间内,直到某个子区间为空,然后在将另一个子区间剩余 的元素全部追加到辅助空间内,然后在将辅助空间的元素覆盖到原来两个子区间即可 归并排序的主要代码是合并,例如:{1,13,24,26},{2,15,27,38}这两个已经有序的子区间进行合并,其过程如下: 从上图可以看出:此时i指向的元素1比j指向的元素2小,所以将1放入辅助空间: 从上图可以看出:此时i指向的元素13比j指向的元2大,所以将2放入辅助空间: 从上图可以看出:此时i指向的元素13比j指向的元15小,所以将13放入辅助空间: 从上图可以看出:此时i指向的元素24比j指向的元15大,所以将15放入辅助空间: 从上图可以看出:此时i指向的元素24比j指向的元27小,所以将24放入辅助空间: 从上图可以看出:此时i指向的元素26比j指向的元27小,所以将26放入辅助空间: 此时这一对区间的左侧区间已经复制到辅助空间中,在将右侧区间的剩余元素追加到辅助空间尾部: 至此来两个区间合并暂未完成!!!,还得把辅助空间中的元素覆盖到这对区间中,才算完成 例:对38,27

排序算法--归并排序

风格不统一 提交于 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 =