排序算法之归并排序及利用归并排序求逆序数
来源:互联网 发布:淘宝平台 编辑:程序博客网 时间:2024/06/03 14:15
排序算法之归并排序
1. 自顶向下的归并排序
中心思想
将待排序的数组平均切分为两半,将前半部分和后半部分分别进行排序,再讲两个有序数组归并到一个数组中
特点
递归,需要额外的空间(辅助数组)来保存切分完成的子数组,主要难点在于合并
操作步骤
- 将待排序数组均分为两半
- 对前半部分进行排序
- 对后半部分进行排序
- 合并两个子数组
- 递归调用以上过程
代码实现
public void sort(int[] a){ int N = a.length;; int b = new int[N];//创建辅助数组 sort(a, 0, N-1);}public void sort(int[] a, int low, int high){ if (low >= high) { return; } int mid = (low + high) / 2;//均分数组 sort(a, low, mid);//排前半部分 sort(a, mid, high);//排后半部分 merge(a, low, high, mid);//归并}private void merge(int[] a, int low, int high, int mid){ for(int i = low; i <= high; i++) { b[i] = a[i]; }//将a[low...high]复制到b[low...high] int j = low;//扫描左半部分 int k = mid + 1;//扫描右半部分 for(int i = low; i <= high; i++){ // 从b[low...high]中依次取出较小的元素放入a[low...high] if (j > mid) { a[i] = b[k++];//若左半部分元素用尽,取右半部分元素 } else if (k > high) { a[i] = b[j++]//若右半部分元素用尽,取左半部分元素 } else if (b[j] < b[k]) { a[i] = b[j++];//两半部分元素都未用尽时,取较小的 } else { a[i] = b[k++]; } }}
2. 自底向上的归并排序
特点
不切分数组,直接两两归并(将每个元素当做大小为1的子数组)、四四归并(将两个大小为2的子数组归并为一个大小为4的数组)…最后对整个数组归并
优点
相对于自顶向下的归并,代码量少
代码实现
public void sort(int[] a){ int N = a.length; int b[] = new int[N]; sort(a, 0, N-1);}private void sort(int[] a, int low, int high){ //sz为子数组的大小,依次为1,2,4,8...N for(int sz = 1; sz < N; sz = sz + sz){ //i为子数组的索引,而子数组大小为N,因而当i移动到靠近边界时边界元素的索引要满足i+sz<N for(int i = low; i < N - sz; i = i + sz + sz){ //当数组大小不是2的偶数倍时,最后一个子数组会比前一个要小,导致该子数组的索引不满足i+2sz-1,而是N-1 merge(a, i, min(i+2sz-1, N-1), i+sz-1); //当N为2的偶数倍时,mid=(i+(i+2sz-1)-1)/2;非偶数倍时,mid=(i+N-1-1)/2,而i<N-sz,可推出此种情况下,(i+(i+2sz-1)-1)<(i+N-1-1),即N为偶数倍,mid可取mid=(i+(i+2sz-1)-1)/2 } }}
归并排序的应用-求逆序数
逆序数指的是逆序数对的个数,在一个序列a[0, 1, 2, …N]中,对任意的i和j,如果i < j且a[i] > a[j],则a[i]和a[j]为逆序数对,一个队列中所有的逆序数对数量之和即为该序列的逆序数。
蛮力法求逆序数
for(int i = 1; i < N; i++){ for(int j = i - 1; j >= 0; j-- ){ if(a[i] < a[j]){ count++; } }}
显然两个循环的存在导致此法复杂度为n的平方。
利用归并排序
merge过程中,由于两个子数组(假设为A和B)已各自有序,用i扫描A,用j扫描B,某次循环中,若a[i] > a[j],则该次循环中得到的逆序数count = A.length - i。对count进行累加后即可得到总逆序数。
由于归并排序时间复杂度为NlogN(数学问题,本文不做证明),因而优于蛮力法。
实现方式
只需在merge方法中计算逆序对数量即可
private void merge(int[] a, int low, int high, int mid){ for(int i = low; i <= high; i++) { b[i] = a[i]; }//将a[low...high]复制到b[low...high] int j = low;//扫描左半部分 int k = mid + 1;//扫描右半部分 for(int i = low; i <= high; i++){ // 从b[low...high]中依次取出较小的元素放入a[low...high] if (j > mid) { a[i] = b[k++];//若左半部分元素用尽,取右半部分元素 } else if (k > high) { a[i] = b[j++]//若右半部分元素用尽,取左半部分元素 } else if (b[j] < b[k]) { a[i] = b[j++];//两半部分元素都未用尽时,取较小的 } else { a[i] = b[k++]; count = count + (mid - low + 1) - j;//累加该次循环的逆序对数量 } }}
阅读全文
0 0
- 排序算法之归并排序及利用归并排序求逆序数
- 归并排序/归并排序求逆序数
- 利用归并排序求逆序数对
- 利用归并排序求逆序数
- 利用归并排序求逆序数对
- 利用归并排序求逆序数
- 归并排序及利用归并排序求逆序对数
- 归并排序-求逆序数算法
- 归并排序之求逆序数
- 归并排序 之 求逆序数
- 二分归并排序之求逆序数
- 数据结构之排序,归并求逆序数
- 归并排序,求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- Java程序员面试题及解答(一)
- spring笔记6-事物及整合hibernate
- Java递归删除树形结构父节点
- matlab读写pgm文件
- C++中的重写、重载、重定义
- 排序算法之归并排序及利用归并排序求逆序数
- hdu 1224
- HDU1272 小希的迷宫 并查集入门||判环
- Java程序员面试题及解答(二)
- ASP.Net 总结
- JNDI
- 欢迎使用CSDN-markdown编辑器
- HDU.2588 GCD (欧拉函数)
- 单例模式