归并排序

归并排序——Java

拈花ヽ惹草 提交于 2020-01-30 00:18:24
文章目录 归并排序 原地归并的抽象方法 自顶向下的归并排序 自底向上的归并排序 三项优化 归并排序 两个有序数组归并成一个更大的有序数组,就叫归并。 归并排序 是一种递归排序算法,就对一个数组来说,可以先将它(递归地)分成两半分别排序,然后将结果归并起来。 时间复杂度:O(NlogN) 空间复杂度:T(N) 原地归并的抽象方法 两个不同的有序数组如何实现归并? 一个最简单直接地方法就是创建一个最够大的第三数组,然后将两个有序数组的元素从大到小的排到第三数组中,这就叫原地归并。 /** * 原地归并的抽象方法 * 归并,数组两边一定要是有序的 */ public static void merge ( Comparable [ ] a , int lo , int mid , int hi ) { //将a[lo..mid]和a[mid+1..hi]归并 int i = lo , j = mid + 1 ; //将a[lo..hi]复制到aux[lo..hi] for ( int k = lo ; k <= hi ; k ++ ) { aux [ k ] = a [ k ] ; } //归并回到a[lo..hi] for ( int k = lo ; k <= hi ; k ++ ) { if ( i > mid ) { a [ k ] = aux [ j ++ ] ; } else

转载-教你如何迅速秒杀掉:99%的海量数据处理面试题

为君一笑 提交于 2020-01-29 08:03:39
原文链接:https://blog.csdn.net/v_july_v/article/details/7382693 作者:July 出处:结构之法算法之道 blog 本文经过大量细致的优化后,收录于我的新书《 编程之法:面试和算法心得 》第六章中,新书目前已上架 京东 / 当当 前言 一般而言,标题含有“秒杀”,“99%”,“史上最全/最强”等词汇的往往都脱不了哗众取宠之嫌,但进一步来讲,如果读者读罢此文,却无任何收获,那么,我也甘愿背负这样的罪名 :-),同时,此文可以看做是对这篇文章: 十道海量数据处理面试题与十个方法大总结 的一般抽象性总结。 毕竟受文章和理论之限,本文将摒弃绝大部分的细节,只谈方法/模式论,且注重用最通俗最直白的语言阐述相关问题。最后,有一点必须强调的是,全文行文是基于面试题的分析基础之上的,具体实践过程中,还是得具体情况具体分析,且各个场景下需要考虑的细节也远比本文所描述的任何一种解决方法复杂得多。 OK,若有任何问题,欢迎随时不吝赐教。谢谢。 何谓海量数据处理? 所谓海量数据处理,无非就是基于海量数据上的存储、处理、操作。何谓海量,就是数据量太大,所以导致要么是无法在较短时间内迅速解决,要么是数据太大,导致无法一次性装入内存。 那解决办法呢?针对时间,我们可以采用巧妙的算法搭配合适的数据结构,如 Bloom filter/Hash/bit-map/堆

归并排序(二路归并)

点点圈 提交于 2020-01-29 05:45:43
#include<stdio.h> #include<algorithm> #define INF 0x3f3f3f3f using namespace std; void merge(int a[],int left,int mid,int right) { int L[100]= {0},R[100]= {0}; int n1=mid-left; int n2=right-mid; for(int k=0; k<n1; k++) L[k]=a[left+k]; for(int k=0; k<n2; k++) R[k]=a[mid+k]; L[n1]=R[n2]=INF;///在L,R,末尾安插一个无穷大,防止两个标记相比较, /// 又防止循环i,j 分别超过n1,n2; int i=0,j=0; for(int k=left; k<right; k++) { if(L[i]<=R[j]) a[k]=L[i++]; else a[k]=R[j++]; } } void mergesort(int a[],int left,int right)///left指开头,right指末尾加1 { if(left+1<right) { int mid=(left+right)/2; mergesort(a,left,mid); mergesort(a,mid,right); merge

用归并排序算法求逆序对数量

雨燕双飞 提交于 2020-01-26 19:27:47
给定一个长度为n的整数数列,请你计算数列中的逆序对的数量。 逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i < j 且 a[i] > a[j],则其为一个逆序对;否则不是。 输入格式 第一行包含整数n,表示数列的长度。 第二行包含 n 个整数,表示整个数列。 输出格式 输出一个整数,表示逆序对的个数。 数据范围 1≤n≤1000001≤n≤100000 输入样例: 6 2 3 4 5 6 1 输出样例: 5 归并: 分治, 先分后合 分的时候(进入递归)是 未排好顺序的,合的时候(递归返回)是排好顺序的俩合的。 如:A 1 4 5 6 7 i mid B 2 3 8 9 j 和后C 1 2 3 4 5 6 7 8 9 在合并的过程中求逆序数 A,B 合的时候 表示A,B的内部已经排序好了,所以A B的内部的当前的逆序数总和为0,但是合并的过程中,要比较A和B中的数,如果出现图上的情况 j的值为2,i的值为4,则A中从i到最后mid 的值都是比j的值要大的,所以2的逆序数为mid-i+1 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=10010; const int N=1e5+10;

归并排序

会有一股神秘感。 提交于 2020-01-26 05:21:15
归并排序的优点 相比于冒泡排序,归并排序的效率更高,它的效率为O(nlogn),而且比起快速排序,归并排序更加稳定。 归并排序的原理 要将一组乱序的数字排列成有序,用归并来思考,就是分治,即大化小,化为最小的有序数字,即只有一个数字时,合并到上一步,将小化大。 步骤为下面的GIF: 用更加清楚的图表现它: 简而言之,就是将小的子序列排序为有序序列合并,这样就没有冒泡的反复比较大小交换的过程,效率更高了。 归并排序的实现 完整代码如下: #include<stdio.h> #include<string.h> void swap(int *a,int *b) { int temp; temp=*a; *a=*b; *b=temp; } void Merge(int *num,int left,int middle,int right) { for(int i=middle+1;i<=right;i++) { for(int j=i;j>left;j--) { if(num[j]>num[j-1]) swap(&num[j],&num[j-1]); } } } void Mergesort(int *num,int left,int right) { if(left<right)//当左右相遇时,递归中止 { int middle=(left+right)/2;/

归并排序mergeSort以及小和问题

时光怂恿深爱的人放手 提交于 2020-01-26 03:23:49
归并排序 时间复杂度O(N*logN),额外空间复杂度O(N),实现可以做到稳定性 #include <cstdio> #include <cstdlib> void merge(int A[], int L, int mid, int R)//两个数组的合并过程,其中要注意的是要合并的两个数组分别一定是有序的 { int i = L, j = mid + 1, k = 0; int *help = (int*)malloc(sizeof(int)*(R - L + 1));//辅助数组 while (i <= mid&&j <= R) { if (A[i] < A[j]) //那边数组数值小放入辅助数组help当中 { help[k++] = A[i++]; } else { help[k++] = A[j++]; } } while (i <= mid)//其余两个while只会实现一个,那个数组没有放入help数组当中,循环放入 { help[k++] = A[i++]; } while (j <= R) { help[k++] = A[j++]; } for (int i = 0; i < k; i++)//最后将辅助数组help当中的数值放入到当前A[]数组的当前排序区域 { A[L + i] = help[i]; } } void sortprosess(int A[]

Ultra-QuickSort(poj 2299归并排序)

萝らか妹 提交于 2020-01-26 01:46:16
http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=232#problem/A B - Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Submit Status Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 9 1 0 5 4 , Ultra-QuickSort produces the output 0 1 4 5 9 . Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a

[算法]——归并排序(Merge Sort)

那年仲夏 提交于 2020-01-24 02:36:47
归并排序 (Merge Sort)与快速排序思想类似:将待排序数据分成两部分,继续将两个子部分进行递归的归并排序;然后将已经有序的两个子部分进行合并,最终完成排序。其时间复杂度与快速排序均为O(nlogn),但是归并排序除了递归调用间接使用了辅助空间栈,还需要额外的O(n)空间进行临时存储。从此角度归并排序略逊于快速排序,但是归并排序是一种稳定的排序算法,快速排序则不然。 所谓 稳定排序 ,表示对于具有相同值的多个元素,其间的先后顺序保持不变。对于基本数据类型而言,一个排序算法是否稳定,影响很小,但是对于结构体数组,稳定排序就十分重要。例如对于student结构体按照关键字score进行非降序排序: // A structure data definition typedef struct __Student { char name[16]; int score; }Student; // Array of students name : A B C D score: 80 70 75 70 Stable sort in ascending order: name : B D C A score: 70 70 75 80 Unstable sort in ascending order: name : D B C A score: 70 70 75 80

排序算法之 归并排序

◇◆丶佛笑我妖孽 提交于 2020-01-24 01:57:02
      归并排序: 简单介绍一下:“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表,它的实现方式大家早都已经熟悉了,无论是顺序存储结构还是链表存储结构,都可以在O(有序表的长度之和)时间内实现,利用归并的思想容易实现排序,假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到 n/2 个长度为2或者为1的有序子序列,在两两归并 一直重复 直到得到一个长度为n的有序序列为止,这种排序方法简称2-路归并排序, 初始的无序表:【49】【38】[65] [97] [76] [13] [27] 一趟归并之后:【38 49】【65 97】【13 76】【27】 二趟归并之后:【38 49 65 97】【13 27 76】 三趟归并之后:【13 27 38 49 65 76 97】 有序表的比较就比较好比了 例如 二趟归并的前后两个有序序列 【38 49 65 97】【13 27 76】 第一个有序序列的 索引开始处与 第二个有序序列的 索引开始处比较,将较小者优先放到排序数组存储 然后将指针向后移动 依次比较直到两个有序序列之一完全使用完毕 将剩余有序序列依次将元素放到排序数组中 组成新的也就是两个有序子序列排序后组合成新的数组 下面是使用java实现的一个简单的讲一个顺序存储的无序序列 归并排序变为一个有序的序列 /** *

归并排序

感情迁移 提交于 2020-01-24 01:50:37
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