归并排序

归并排序求逆序对

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-13 22:24:29
归并求逆序对 归并求逆序对 是分治的一个经典例子。 简述算法: 利用归并把序列对半分,在一般的归并过程中,我们在前后两部分各设两个指针,按照大小顺序合并成一个序列。 我们要做的就是在这个过程中记录逆序对个数,什么情况下会有逆序对呢? 无非是在前面的数比在后面的数大(翻译过来:在前半部分的数比在后半部分的数大) 设前半部分的指针为t1,后半部分的指针为t2 如果a[t1] > a[t2],那么t1~mid的元素一定都比t2大,一定都可以与t2形成逆序对: ans+= (mid- t1+ 1)+1 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 5 using namespace std; 6 7 const int N=100010; 8 int a[N],b[N],n,ans=0; 9 10 void merge(int l,int r) 11 { 12 if (l==r) return; 13 int mid=(l+r)>>1; 14 merge(l,mid); 15 merge(mid+1,r); 16 int t1=l; 17 int t2=mid+1; 18 for (int i=l;i<=r;i++) 19 { 20 if ((t1<=mid&&a[t1]<=a[t2])||t2>r) { 21

剑指offer-51

南楼画角 提交于 2020-01-13 07:32:55
数组中的逆序对 解法一:暴力解法,依次遍历每个值,再计算余下数字与其形成逆序的次数 解法二:仿照归并法。暴力解法在判断某个时,会多次遍历余下节点,仿照归并排序,每次分解依次,在合并的过程中进行计数,从两组待归并的最后一位开始合并,因为已经是排序好的,归并中对前面的数字就不必再比较而直接计算,还是要有图说明比较好 解法一 int InversePairs(int* data, int length) //暴力法 { if (data == nullptr || length <= 1) return 0; int cnt = 0; for (int i=0;i<length;i++) { for (int j=i+1;j<length;j++) { if (data[j] < data[i]) cnt++; } } return cnt; } 解法二: int InversePairs(int* data, int start, int end, int* tempArr)//归并法 { if (start >= end) return 0; int mid = (start + end) >> 1; int cnt = 0; cnt += InversePairs(data, start, mid, tempArr); cnt += InversePairs(data, mid +

POJ-排序-归并排序与逆序对

最后都变了- 提交于 2020-01-13 07:21:24
排序:归并排序与逆序对 一、概念 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 时间复杂度:O(nlogn) 二、算法描述 1.将数组拆分成单个元素,两两归并。 2.对于两组同向有序数组,首先判断两组数的首位的大小,并将较小的数保留到一个新数组中。 3.再比较较小组数的第二位和另一组数的第一位,仍然保留较小的数,这样就保证新数组的有序,需要注意的是当任意一组数为空时,就自然将另一组数的剩下数接到新数组后(因为剩下的树肯定比刚放进去的大)。 三、逆序对 逆序对问题设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 A[i], A[j]这个有序对称为 A 的一个逆序对,也称作逆序数。 例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。 四、归并排序与逆序对 因为在排序的合并过程中是将两组有序数进行比较,所以根据逆序对的定义,在数组下标 i 小于 j 时,如果有 a[i] 大于 a[j]

归并排序

流过昼夜 提交于 2020-01-11 08:07:24
public static void main(String[] args) { int[] array={49,38,65,97,76,13,27,49,78,34,12,64,1}; int[] newArray = myMergeSort(array, 0, array.length - 1); System.out.println("排序之后:"); for(int i=0;i<newArray.length;i++){ System.out.print(newArray[i]+" "); } System.out.println(); } /** * 包含leftIndex和rightIndex * @param arr * @param leftIndex * @param rightIndex * @return */ public static int[] myMergeSort(int[] arr,int leftIndex,int rightIndex){ if(leftIndex==rightIndex){//按照切分法,当leftIndex==rightIndex时,就代表只有一个元素了,切到最小了,也就可以返回了 return new int[]{arr[leftIndex]}; } int midIndex=leftIndex+(rightIndex

排序算法的指标性能比较

孤者浪人 提交于 2020-01-10 20:22:16
表一 排序方法 平均时间复杂度 最好时间复杂度 最坏时间复杂度 辅助空间 稳定性 冒泡排序 O(n 2 ) O(n) O(n 2 ) O(1) 稳定 简单选择排序 O(n 2 ) O(n 2 ) O(n 2 ) O(1) 稳定 直接插入排序 O(n 2 ) O(n) O(n 2 ) O(1) 稳定 希尔排序   O(nlogn)~O(n 2 ) O(n 1.3 ) O(n 2 ) O(1) 不稳定 堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定 归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定 快速排序 O(nlogn) O(n) O(n 2 ) O(logn)~O(n) 不稳定 一,七种排序算法的性能指标说明: (1)冒泡排序:最坏的情况,即为序列处于逆序的情况,此时需要比较的次数为n(n-1)/2;最好的情况就是序列本身有序,那么需要比较的次数为n-1次,平均o(n 2 ) (2)简单选择排序:无论最好最差情况,其比较次数均为n(n-1)/2,对于交换次数而言,最好的情况,交换0次,最差的情况,交换次数为n-1次,那么综合比较和交换的次数,平均时间复杂度为o(n 2 ) (3)直接插入排序:最好的情况,即排序表本身是有序的,比较了n-1次,时间复杂度为o(n);最坏的情况,即待排序为逆序,此时需要比较(n+2)*(n

05排序之归并排序

允我心安 提交于 2020-01-10 05:53:32
归并排序 数据结构整理目录 基本介绍 归并排序是利用 归并 的思想实现的排序方法 该算法采用经典的 分治策略 (分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的个答案“修补”在一起,即分而治之) 分析 再来看看 治 阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤: 代码实现 package F排序 ; import java . util . Arrays ; /** * @Author Zhou jian * @Date 2020 ${month} 2020/1/4 0004 16:54 * 归并排序 */ public class MergeSort { public static void main ( String [ ] args ) { int [ ] arr = { 8 , 4 , 5 , 7 , 1 , 3 , 6 , 2 } ; int [ ] temp = new int [ 8 ] ; //归并排序需要额外的空间 mergeSort ( arr , 0 , arr . length - 1 , temp ) ; System . out . println (

归并排序

試著忘記壹切 提交于 2020-01-09 13:08:39
归并排序 const int N = 1e6 + 10; int q[N], tmp[N]; void merge_sort(int q[], int l, int r) { if (l >= r)return; int mid = l + r >> 1; merge_sort(q, l, mid), merge_sort(q, mid + 1, r); int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) if (q[i] <= q[j])tmp[k++] = q[i++]; else tmp[k++] = q[j++]; while (i <= mid)tmp[k++] = q[i++]; while (j <= r)tmp[k++] = q[j++]; for (i = l, j = 0; i <= r; i++, j++)q[i] = tmp[j]; } 来源: https://www.cnblogs.com/fsh001/p/12170861.html

归并排序

梦想的初衷 提交于 2020-01-08 14:19:49
对于归并排序,它的时间复杂度是 O(nlogn) ,它的最差时间复杂度是这个,最好的时间复杂度是这个,平均时间复杂度也是这个。 归并排序有一个很重要的思想在里边,那就是分治的思想。 算法的过程其实就两步,一个是分,一个是治。 # # 归并算法的过程图 可以看到的是,所谓的分就是拆分,治就是将两个有序的序列合并成为一个有序的序列。 # # 下边看代码过程 public class MergetSort { public static void main(String[] args) { //int arr[] = { 8, 4, 5, 7, 1, 3, 6, 2 }; // //测试快排的执行速度 // 创建要给80000个的随机的数组 int[] arr = new int[8000000]; for (int i = 0; i < 8000000; i++) { arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数 } System.out.println("排序前"); Date data1 = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String

归并排序--递归

老子叫甜甜 提交于 2020-01-07 20:25:35
直接看代码 package com.lm.digui; public class GuiBinSort { public static void main(String[] args) { int[] arr = {1, 2, 3, 5, 8}; System.out.println(guibinNumber(arr, 0, arr.length - 1, 5)); } private static int guibinNumber(int[] arr, int low, int high, int keyvalue) { if (low < high) { int mid = (low + high) / 2; if (keyvalue == arr[mid]) { return mid; } else if (keyvalue < arr[mid]) { return guibinNumber(arr, low, mid - 1, keyvalue); } else if (keyvalue > arr[mid]) { return guibinNumber(arr, mid + 1, high, keyvalue); } } return -1; } } 来源: https://www.cnblogs.com/limingming1993/p/12154004.html

归并排序

你。 提交于 2020-01-07 16:28:32
二路归并排序 //二路归并排序 //分治法 //自底向上的二路归并排序算法 #include<stdio.h> #include<malloc.h> void disp(int a[],int n){ int i; for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); } void Merge(int a[],int low,int mid,int high){ //将a[low..mid]和a[mid+1..high]两个相邻的有序子序列归并为一个有序子序列a[low..high] int *tmp; int i = low,j = mid+1,k = 0; tmp = (int *)malloc((high - low + 1)*sizeof(int)); while(i < mid && j < high){ if(a[i] <= a[j]){ tmp[k] = a[i]; i++; k++; } else{ tmp[k] = a[j]; j++; k++; } } while(i <= mid){ tmp[k] = a[i]; i++; k++; } while(j <= high){ tmp[k] = a[j]; j++; k++; } for(k = 0,i = low;i<=high;k++,i++) a[i] =