排序之逆序數

2021-06-09 15:39:28 字數 1499 閱讀 7354

求陣列a[1:n]的逆序對數, 如果ia[j]則(i,j)則稱為乙個逆序對。

陣列<2,3,8,6,1>的逆序對數就是5.

求逆序對數最簡單的演算法就是把陣列的元素兩兩比較下,判斷是否逆序對,複雜度為o(n^2).

有沒有複雜度更低的演算法呢?是否可以從排序演算法的角度去思考逆序數?

排序的過程就是要把逆序的數的次序進行糾正的過程,複雜程度很有可能與逆序對的數量是有關的。

1. 逆序對的數量與陣列中重複元素的數量是無關係的,因此,不穩定的排序方法如快排等不在考慮範圍內

2. 穩定排序演算法中,先看氣泡排序,每次進行冒泡交換陣列元素時,相鄰元素交換位置,不影響這兩個元素與陣列其它元素之間的順序(逆序)關係,也就是說,每冒泡交換一次,陣列逆序對數減一。冒泡交換的總次數就等於逆序對數。

3. 選擇排序和氣泡排序相似,插入元素位置移動時不影響的是該元素之後的陣列的逆序數對數量,而插入元素之前的陣列是已經排好序的,逆序對為0,每次插入逆序對數的改變量等於元素原始位置與插入位置之間的偏移。

4.歸併排序,逆序對數的改變發生在合併這一步。陣列分成兩半a=[a1,a2],a1,a2都是排序好的陣列,合併時指向a1的指標為i,指向a2的指標為j,如果a2的元素均比a1的元素大,逆序對數量為0,如果a2的元素全比a1的小,那麼逆序數為length(a2)*length(a1)。可以修改歸併排序,當j++時,判斷當前a1中還有多少個元素沒有被歸併,當前合併的a2元素產生的逆序對數就是多少,累積求和就可以搞定。

修改冒泡和選擇排序求逆序數複雜度是o(n^2),利用歸併排序求逆序對數的演算法複雜度可以降低到o(nlogn)

/*

* nixushu.c

* * created on: 2012-9-19

* author: sangerhoo

*/#includeusing namespace std; /* 歸併求逆序對數, arr 儲存最終有序結果 * 在函式外申請乙個臨時陣列作為引數傳入 * 避免遞迴不斷建立臨時陣列的開銷 */

int merge(int * arr, int beg, int mid, int end, int * tmp_arr) else

} while (i <= mid)

while (j <= end)

return inversion;

}int mergeinversion(int * arr, int beg, int end, int * tmp_arr)

return inversions;

}/* 測試序列 :answer: 10 */

void main() ;

int arrcopy[10]; // 臨時陣列

memcpy(arrcopy,testpoint,sizeof testpoint);

printf("the num of inversions is: %d\n",

mergeinversion(testpoint, 0, 9, arrcopy));

}}

求逆序數 逆序數 歸併排序

求排列的逆序數 分治 一 題目描述 總時間限制 1000ms 記憶體限制 65536kb 描述 在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序來評價它們之間的差異。考慮1...

逆序數字排序

現在給你一組數字,要求你把每乙個數字逆序 如123變為321 之後進行排序,按從小到大的順序排列 第一行乙個數字t t 20 表示共有t組測試資料。下面t行 每組開始有乙個數字x x 20 表示該組有x個數字,後面是該組的x x 10000 個數字。每組資料輸出一行,輸出按從小到大排列好的數字。24...

歸併排序 之 求逆序數

前幾天看樹狀陣列,昨天做求逆序數的題,發現歸併排序求逆序數更快一點,或者說是排序的時候順便把逆序數給求了,於是學了一下,順便整理一下。歸併排序 說白了就是把一列數 遞迴 的分解為多個有序的子串行,然後再把子序列合併 為一列有序的數。這就涉及兩個過程 1,遞迴劃分 把序列分成個數盡量相等的兩部分,兩邊...