要求: 借鑑歸併排序的算法,在歸併的過程中,統計逆序對的個數,並記錄下具體的逆序對。設計一個分治算法,並用C/C++語言實現編程。
#include "stdio.h"
int count=0;
void Merge(int r[],int r1[],int s,int m,int t) // 合併子序列
{
int i=s,j=m+1,k=s;
int b;
while(i<=m && j<=t){
if(r[i]<=r[j]){ // 取較小者放入r1[k]中
r1[k++]=r[i++];
}
else{
count+=m-i+1; // 若左邊數大於右邊數,則左邊數及其後邊數都大於該右邊數
b=i;
while(b<=m){
printf("[%d,%d]\n",r[b],r[j]);
b++;
}
r1[k++]=r[j++];
}
}
while(i<=m) // 若第一個子序列沒處理完,則進行收尾處理;下同
r1[k++]=r[i++];
while(j<=t)
r1[k++]=r[j++];
}
void MergeSort(int r[],int s,int t){ // 對序列r[s]~r[t]進行歸併排序
int m,r1[1000],i;
if(s==t)
return ;
else{
m=(s+t)/2; // 劃分
MergeSort(r,s,m); // 子問題1
MergeSort(r,m+1,t); // 子問題2
Merge(r,r1,s,m,t); // 合併
for(i=s;i<=t;i++)
r[i]=r1[i];
}
}
int main(){
int r[]={23,13,35,6,19,50,28,38,26,17,45},i;
MergeSort(r,0,10); // 三個參數分別爲待查數組、起始下標、截止下標
for(i=0;i<=10;i++)
printf("%d ",r[i]);
printf("\n一共 %d個逆序對\n",count);
}
注:參考書籍 《算法設計與分析(第二版)》 王紅梅 胡明 編著