规并排序 以及 在其基础上的逆序对
写递归程序的时候,一定要注意其递归体的逻辑,另外假设子问题已经解决。
辅助函数只要解决好当前层自问体就好了,不要思考太多层次的东西,当然特殊的递归需求会有考虑多层次的东西。
merge(int l, int m, int r, int *a) {
l -> m
m+1->r 要合并
求逆序对个数的时候,可以在规并的过程中来数逆序对数。
L[]有序,R[]有序
那么L[I] <= R[J]时候,不需要累计逆序对数
否则L[I] > R[J]那么说明L[I] - > L[LEN_OF_LEFTPART] 都是与R[J]有逆序的关系。所以插入R[J]时候发现的逆序对数目是LEN_OF_LEFTPART-I+1
两边规并知道完成
return 当前层级的合并过程中的逆序对的个数。
}
merge_sort(int l, int r, int *a){
int cnt = 0, m = (l+r)>>1;
if( l < r ){
cnt += merge_sort(l, m, a); 左规并时候有几个逆序对
cnt += merge_sort(m+1,r, a);右规并的时候有几个逆序对
cnt += merge(l, m, r, a);当前曾规并的时候有几个逆序对,这个时候因为已经假设了右边和左边的是有序的。
}
return cnt;
}
源代码:
//============================================================================
// Name : integerPartition.cpp
// Author : jry
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int merger(int l, int m, int r, int* a){
int llen = m-l+1, rlen = r-m;
int *L = new int [(llen)];
int *R = new int [(rlen)];
int i = l, j = 0, k = 0, ttcnt = 0;
for(; i <= m; i++) L[j++] = a[i];
for(j = 0; i <= r; i++ ) R[j++] = a[i];
i = j = 0;
k = l;
while(i < llen && j < rlen){
if(L[i] <= R[j]) a[k++] = L[i++];
else {
a[k++] = R[j++];
ttcnt += llen - i;
}
}
while( i < llen ) a[k++] = L[i++];
while( j < rlen ) a[k++] = R[j++];
delete[] (L);
delete[] (R);
return ttcnt;
}
int merger_sort(int l, int r, int *a){
int m = (l+r) / 2;
int tcnt = 0;
if( l < r ) {
tcnt += merger_sort(l, m, a);
tcnt += merger_sort(m+1, r, a);
tcnt += merger(l, m, r, a);
}
return tcnt;
}
int main() {
int a[] = {4, 1, 2, 3, 5, 1};
bool TESTMSort = false;
int n = sizeof(a)/sizeof(int);
if(TESTMSort) { for( int i = 0; i < n; i ++ ) cout << a[i] << " "; cout << endl;}
cout << "逆序对数: " << merger_sort(0, n-1, a) << endl;
cout << "DONE" << endl; // prints DONE
return 0;
}