1.用树状数组求逆序数
缺点:只能对整数求逆序数
#include "TreeArray.h" /* 算法: 由树状数组求逆序对。加入元素i即把以元素i为下标的a[i]值+1,从队尾到队首入队, 每次入队时逆序对数 += getsum(i - 1),即下标比它大的但是值比它小的元素个数。 因为树状数组不能处理下标为0的元素,每个元素进入时+1,相应的其他程序也要相应调整。 求出原始的序列的逆序对个数后每次把最前面的元素移到队尾,逆序对数即为 原逆序对数+比i大的元素个数-比i小的元素个数,因为是0..n,容易直接算出 */ int NiXuShu(int Array[], int n) { TreeArray ta(1); ta.clear(); int i, sum = 0; for (i = n-1; i >= 0; i --) { ta.modify(Array[i]+1, 1); sum = sum + ta.sum(Array[i]); } return sum; }
2.用归并排序求逆序数
缺点:会改变数组中的值
#include <iostream> using namespace std; #define MAX 50005 int rs, tar[MAX]; void merge(int Array[], int l,int m,int r){ int l1=l,l2=m+1,pp=0; while(l1<=m&&l2<=r){ if(Array[l1]<=Array[l2]){ tar[pp++]=Array[l1++]; }else{ tar[pp++]=Array[l2++]; rs+=m-l1+1; } } while(l1<=m)tar[pp++]=Array[l1++]; while(l2<=r)tar[pp++]=Array[l2++]; for(int i=l,j=0;i<=r;i++,j++){ Array[i]=tar[j]; } } void mergesort(int Array[], int l,int r){ if(l>=r)return; int m=(l+r)/2; mergesort(Array, l, m); mergesort(Array, m+1, r); merge(Array, l, m, r); } int NiXuShu(int Array[], int n) { rs = 0; mergesort(Array, 0, n-1); return rs; }