求出一列數中的“逆序對”的個數;所謂“逆序對”就是指數的大小與其在序列中的順序相反的一對數;例 如:<3,4,2,1,3>中“逆序對”有<3,2>,<3,1>,<4,2>,<4,1>,<4,3>這5個;要求時間複雜度爲O(nlogn);
#include <stdio.h>
void PrintTheRel(int i, int j);
void Sort(int Array[100], int end);
void GetTheRel(int Front[50],int len1, int Back[50], int len2);
void GetResult(int bundary, int source[100], int low, int high);
void main()
{
int Source[100];
int temp, length, times;
printf("Please enter the length:");
scanf("%d", &length);
printf("/nPlease enter the elements:");
for (temp=0; temp < length; temp++)
scanf("%d", &Source[temp]);
times = (int)(length/2);// 求界限
GetResult(times, Source, 0, length-1);
}
///////////////////////////////////////////////////////////////////////
//
// 函數名 : GetResult
// 功能描述 : 通過遞歸算法實現數列逆序列的求解
// 參數 : int bundary 二分法中涉及的分界點
// 參數 : int source[100] 一個待求序列
// 參數 : int low 序列的開始座標
// 參數 : int high 序列的最後座標
// 返回值 : void
//
///////////////////////////////////////////////////////////////////////
void GetResult(int bundary, int source[100], int low, int high)
{
int i,k=0;
int Front[50], Back[50];
if(high-low < 1) /*假如只有一個數就彈出遞歸堆棧 */
return;
else
{
for(i=low; i < bundary; i++)
Front[k++] = source[i];/*得到一個前一段的臨時的數組 */
k=0;
for(i=bundary; i <= high; i++)
Back[k++] = source[i]; /*得到一個後一段的臨時的數組 */
Sort(Front, bundary-1-low);/*對前一段進行排序 */
Sort(Back, high-bundary); /*對後一段進行排序 */
// 得到一組逆序對,這是求已經分好界的兩邊界的逆序對關係
GetTheRel(Front, bundary-low, Back, high - bundary + 1);
// 遞歸求左半部分
GetResult((int)((bundary-low +1) / 2)+low, source, low, bundary-1);
// 遞歸求右半部分
GetResult((int)((high-bundary+1) / 2)+bundary, source, bundary, high);
}
}
///////////////////////////////////////////////////////////////////////
//
// 函數名 : GetTheRel
// 功能描述 : 得到已經分成兩半時的逆序對
// 參數 : int Front[50] 前一部分的己排序序列
// 參數 : int len1 前一個序列的長度
// 參數 : int Back[50] 後一部分的已排序序列
// 參數 : int len2 後一個序列的長度
// 返回值 : void
//
///////////////////////////////////////////////////////////////////////
void GetTheRel(int Front[50], int len1, int Back[50], int len2)
{
int i=0, j=0, k;
// 通過一次掃描可以將兩個部分的逆序對全找出來
while ((i<len1) && (j <len2))
{
while (Front[i] > Back[j] && (i<len1) && (j <len2))
{
// 因爲己經按遞增排好序的所以將前半部分i下面的全部輸出
for(k=i; k<len1;k++)
PrintTheRel(Front[k], Back[j]);
j++;/*當輸出之後,後半部分指針加一 */
}
i++; /*前半部分沒有比當前後半部分的值大將加一 */
}
}
///////////////////////////////////////////////////////////////////////
//
// 函數名 : Sort
// 功能描述 : 現在只是爲了方便採用的是冒泡排序,可以採用O(nlogn)的算法。
// 參數 : int Array[100] 需要排序的數組
// 參數 : int end 數組默認從0開始,到end結束
// 返回值 : void
//
///////////////////////////////////////////////////////////////////////
void Sort(int Array[100], int end)
{
int i, j, temp;
// 自己認爲這樣的冒泡寫法最清晰
for (i=end; i >0; i--)
for (j=0; j < i; j++)
if (Array[j] > Array[j+1])
{
temp = Array[j];
Array[j] = Array[j+1];
Array[j+1] = temp;
}
}
///////////////////////////////////////////////////////////////////////
//
// 函數名 : PrintTheRel
// 功能描述 : 格式打印
// 參數 : int i 參數1
// 參數 : int j 參數2
// 返回值 : void
//
///////////////////////////////////////////////////////////////////////
void PrintTheRel(int i, int j)
{
printf("<%d, %d>/n", i, j);
}
輸入輸出舉例:
Please enter the length:10
Please enter the elements:9 8 7 6 5 4 3 2 1 0
<5, 0>
<6, 0>
<7, 0>
<8, 0>
<9, 0>
<5, 1>
<6, 1>
<7, 1>
<8, 1>
<9, 1>
<5, 2>
<6, 2>
<7, 2>
<8, 2>
<9, 2>
<5, 3>
<6, 3>
<7, 3>
<8, 3>
<9, 3>
<5, 4>
<6, 4>
<7, 4>
<8, 4>
<9, 4>
<7, 5>
<8, 5>
<9, 5>
<7, 6>
<8, 6>
<9, 6>
<8, 7>
<9, 7>
<9, 8>
<6, 5>
<3, 0>
<4, 0>
<3, 1>
<4, 1>
<3, 2>
<4, 2>
<4, 3>
<2, 0>
<2, 1>
<1, 0>
Press any key to continue