归并排序
归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使 每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
首先盘点一下C++的各种排序算法:qsort(快速排序), merge_sort(归并排序), heap_sort(堆排序),以及最为强大的sort,这个函数的实现我们并不能够确定他将用什么排序算法。
排序算法那么多,为什么只有归并排序需要详细学习实现呢?
首先归并排序是分治思想的重要代表,其实分治的代码大部分都与归并排序非常类似。而且归并排序还可以用来求逆序对。
核心思想:
对[l, r]进行排序时,先对[l, m]和[m + 1, r]进行排序,然后对两个有序数列进行合并。
其中对两个有序数字的合并是用两个指针O(1) 实现的。每次归并时从两个数组中求最小值,而最小值有一定是左边数组的第一个或右边数组的第一个,于是可以用两个指针对两个数组扫描来实现。
#include <algorithm> #include <iostream> #include <cstring> using namespace std; const int MAXN = 12000; int a[MAXN]; //原数组 int b[MAXN]; //中间数组 int ans = 0; //逆序对个数 void mergesort(int l, int r) //归并排序 { if (l == r) return; int mid = (l + r) >> 1; mergesort(l, mid); mergesort(mid + 1, r); int p1 = l, p2 = mid + 1; for (int i = l; i <= r; ++i) if (p1 <= mid) if (p2 <= r) if (a[p1] < a[p2]) b[i] = a[p1++]; else b[i] = a[p2++]; else b[i] = a[p1++]; else b[i] = a[p2++]; for (int i = l; i <= r; ++i) a[i] = b[i]; } void mergesort(int l, int r) //求逆序对个数 { if (l == r) return; int mid = (l + r) >> 1; mergesort(l, mid); mergesort(mid + 1, r); int p1 = l, p2 = mid + 1; for (int i = l; i <= r; ++i) if (p1 <= mid) if (p2 <= r) if (a[p1] < a[p2]) b[i] = a[p1++]; else b[i] = a[p2++], ans += mid - p1 + 1; else b[i] = a[p1++]; else b[i] = a[p2++]; for (int i = l; i <= r; ++i) a[i] = b[i]; }