归并排序和快速排序存在一些衍生问题,比如计算一个数组中逆序对的数量。
首先介绍逆序对的概念:从数组中随意选出一对数,若前者大于后者,则称为逆序对。而一个数组中的逆序对的数量可以衡量数组的有序程度,比如一个完全有序的数组1 2 3 4 5 6 7,其逆序对的数量为0,数组完全有序;而7 6 5 4 3 2 1中逆序对的数量达到最大值,所以数组的有序程度很低。
对于求解逆序对数量的问题,可以采用暴力解法,其时间复杂度为O(n^2),代码如下:
template<typename T>
int reserveOrder(T arr[], int n)
{
int num = 0; //逆序对数量
for(int i = 0; i < n; i++)
{
for(int j = i + 1; j < n; j++)
{
if(arr[j] < arr[i])
{
++num;
}
}
}
return num;
}
求解逆序对的另一个方法,可以使用归并排序来实现:
在归并过程中,若当前 i 所指元素小于 j 所指元素的值,则 i 所指元素相对于 j 所指元素后面的所有元素都是顺序的;若当前 i 所指元素大于 j 所指元素的值,则 i 所指元素后面的所有元素(在该子序列2 3 6 8中)相对于 j 所指的元素都是逆序的,所以此时可以将逆序数量加4。利用归并排序来求解逆序对数量的优点在于,不需要一对一对的判断是否为逆序对,可以经过一次判断确定一个子序列中的所有元素都与另一个元素为逆序对。
完整代码如下:
SortTestHelper.h文件(包含辅助函数)
#include <iostream>
#include <cstdlib>
#include <ctime> //clock()、CLOCKS_PER_SEC
#include <cassert> //包含函数assert()
using namespace std;
namespace SortTestHelper
{
//辅助函数 - 随机产生一个数组
int* generateRandomArray(int n, int RangeL, int RangeR) //返回数组首地址
{
//判断Ra