归并排序计算逆序对数目
2016-05-27 15:47
232 查看
数组a中的一个逆序对(a[i], a[j])是i<j且a[i]>a[j]。平凡的方法是遍历所有数对,时间复杂度为O(n^2),利用归并排序的思想可以降至O(nlgn)。
运行结果如下:
#include <cstdio> #include <vector> #include <limits> #include <cstdlib> #include <ctime> using namespace std; //平凡的计算逆序数的方法 //比较数组中的所有C(n, 2)个数对 //时间复杂度O(n^2) int trival_inverse(const vector<int> &a, int first, int last) { int count = 0; int i, j; for (i = first; i < last; ++i) { for (j = i + 1; j < last; ++j) { if (a[i] > a[j]) ++count; } } return count; } //当[first, mid)和[mid, last)有序时计算数组的逆序对数目 //左半部分和右半部分均已有序,无逆序对 //每次比较固定右半段某个数,找出左半段中所有能构成逆序对的数 //当first <= i < mid, mid <= j < last时 //若a[i] > a[j] //则左半部分a[k](k>=i)均与a[j]构成逆序对,共mid - first - i个 //左半部分a[k](k<i)均<=a[j],不产生逆序对 //若a[i] <= a[j],也不产生逆序对 int merge(vector<int> &a, int first, int mid, int last) { vector<int> left(a.begin() + first, a.begin() + mid); vector<int> right(a.begin() + mid, a.begin() + last); left.push_back(numeric_limits<int>::max()); right.push_back(numeric_limits<int>::max()); int count = 0; int i = 0, j = 0, k = 0, left_len = mid - first; for (k = first; k < last; ++k) { if (left[i] <= right[j]) { a[k] = left[i++]; } else { a[k] = right[j++]; count += left_len - i; } } return count; } //结合归并排序,将数组分为两段,左右两段分别排序并计算各自的逆序对数目c1, c2 //这不会影响左右两段一起产生的逆序对数目c0,再计算出c0,总的逆序对数目即为c1 + c2 + c0 int merge_inverse(vector<int> &a, int first, int last) { if (first >= last - 1) return 0; int count = 0; int mid = (first + last) >> 1; count += merge_inverse(a, first, mid); count += merge_inverse(a, mid, last); count += merge(a, first, mid, last); return count; } int main() { int n = 1; for (int i = 0; i < 7; ++i) { vector<int> a(n, 0); srand(time(NULL)); for (int i = 0; i < n; ++i) { a[i] = rand() % 10000; } int beg, end; beg = clock(); printf("n=%d\n", n); printf("%d\t", trival_inverse(a, 0, a.size())); end = clock(); printf("time:%d\n", end - beg); beg = clock(); printf("%d\t", merge_inverse(a, 0, a.size())); end = clock(); printf("time:%d\n", end - beg); n *= 10; } return 0; }
运行结果如下:
相关文章推荐
- 举例讲解C语言对归并排序算法的基础使用
- java实现归并排序算法
- C++实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等
- C++实现自底向上的归并排序算法
- C++实现自顶向下的归并排序算法
- JavaScript希尔排序、快速排序、归并排序算法
- Java实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等
- Java排序算法总结之归并排序
- C++归并排序算法实例
- Javascript排序算法之合并排序(归并排序)的2个例子
- 归并排序的递归实现与非递归实现代码
- Java编程中实现归并排序算法的实例教程
- java二路归并排序示例分享
- java实现归并排序算法
- 归并排序的实现代码与思路
- JavaScript希尔排序、快速排序、归并排序算法
- 逆序对
- leetcode 虐我篇之(二) Two Sum
- In-place Merge Sort 原地并归排序
- 使用Java完成《算法导论》习题2.3-2