分治模式的步骤:分解、解决、合并。
MergeSort的思想也是如此,把数组从中间分成两部分,然后分别排好序,再用merge将两个已经排好序的
数组归并成一个数组。子数组的排序,可以再用MergeSort,即递归。所以,归并排序的核心是归并。
// Mergesort.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
#include
#include
using namespace std; const int MAX=30;//MAX是哨兵牌无穷大,因为测试时的数都小于30,可用climits库中的INT_MAX等等 //nums是要排序的数组,p,q,r是下标,满足p<=q
& nums, int p, int q,int r)//p是左端,q是右端 { if(p<=q&& q<=r&&r<=nums.size()) { int n1=q-p+1,n2=r-q; vector
L(n1+1),R(n2+1);//临时数组多一个空间,为了放哨兵牌 int i,j; for(i=0;i
R[j]) { nums[k]=R[j++]; }else { nums[k]=L[i++]; } } } } //分治法,左右都排好序了,再归并 void MergeSort(vector
& nums, int p, int r) { int q,inversion=0; if(p
下面介绍逆序对的概念:假设A[1...n]是一个有n个不同数的数组。若i<j且A[i]>A[j],则称对偶(i,j)为A 的一个逆序对。 分治解决:把A[1...n]根据下标分成两部分,A[1...q]和A[q+1,...,n]。它的逆序对数分为3部分,A[1...q]的逆序对数
和A[q+1,...,n]的逆序对数,以及它俩之间组成的逆序对。前面两个是同一问题的子问题,递归求,即可。只需考虑
它俩之间的逆序对,可以考虑再归并时计数,A[1...q]在left数组中,A[q+1,...,n]在right数组中,当left中的数大于right
内的数时就有逆序对了,计数见代码。
// cha12_2Count_Inversions.cpp : 定义控制台应用程序的入口点。
//
// cha2_1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
#include
#include
using namespace std; const int MAX=30; int MergeInversion(vector
& nums, int p, int q,int r) { int inversions=0; if(p<=q&& q<=r&&r<=nums.size()) { int n1=q-p+1,n2=r-q; vector
L(n1+1),R(n2+1); int i,j; for(i=0;i
R[j]) { inversions+=n1-i;//为什么是n1-i呢?若有L[i]>R[j],因为L是排好序的,所以L[i]后面的数也一定大于R[j] //即它们都可以与R[j]组成逆序对,一共有n1-i个。 nums[k]=R[j++]; }else { nums[k]=L[i++]; } } } return inversions; } int MergeSort(vector
& nums, int p, int r) { int q,inversion=0; if(p