在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。
比如3 4 1 2這個陣列有4對逆序:分別是[3,1] [4,1] [3,2] [4,2]。
本文使用歸併排序來求逆序數。
假設歸併排序已經進行到了如上這個狀態,正要把兩個長度為2的有序子串行,合併成乙個長度4的有序序列。
i
指向前子串行。j
指向後子串行。很明顯,當j
指向元素小於i
指向元素時,就肯定是產生了逆序對了。而逆序對的個數則與i
指向元素在前子串行中的位置有關,是從i
開始到前子串行的最後元素的個數(包括i
和最後元素來統計),通俗地講,就是如果j
比i
小,那麼j
肯定也比i
之後的元素還小(當然這裡是指在前子串行中的範圍)。
如上圖,1比3小,那麼1必然也比3後面的元素4小。
def
merge
(start,former,latter,end,src,des)
: gap = end -start +
1 i = start
j = latter
count =
0for step in
range
(gap):if
(i<=former)
and(j<=end)
:if src[i]
<= src[j]
: des[start+step]
= src[i]
i +=
1else
:#只有進入else才代表有逆序對
#j元素比i元素小,那麼j肯定也比前子串行中的i後面的元素小
des[start+step]
= src[j]
j +=
1 count += latter - i#記錄下來前子串行i之後元素個數,包括i
elif
(i<=former)
: des[start+step]
= src[i]
i +=
1elif
(j<=end)
: des[start+step]
= src[j]
j +=
1for step in
range
(gap)
: src[start+step]
= des[start+step]
return count
defmerge_sort
(start,end,src,des)
:if start < end:
count =
0 mid =
(start+end)//2
count += merge_sort(start,mid,src,des)
#加上左子串行的逆序對數
count += merge_sort(mid+
1,end,src,des)
#加上右子串行的逆序對數
count += merge(start,mid,mid+
1,end,src,des)
#再加上左右子串行合併時,發現的逆序對數
return count
return
0#遞迴終點返回0
defcopy_array
(arr)
:return
[none
for i in
range
(len
(arr))]
arr =[9
,8,4
,5,7
,1,3
,6,2
]temp = copy_array(arr)
n =len
(arr)
num = merge_sort(
0,n-
1,arr,temp)
#print(arr)
print
(num)
**改自本人另一篇部落格歸併排序 改進歸併,其中的基本歸併排序的**。 歸併排序 逆序數
對於數列a,將其二分地拆分為b,c 先將b,c分別排序好,再合併b,c即為總的排序,不過在合併的過程中我們可以算出逆序數哦。其原理網上很多,我這裡不再贅述,只給出實現 include include define ll long long using namespace std ll mergeso...
逆序數(歸併排序)
分而治之 分 每次從中間劃分開,直到有序為止,即乙個整數 void merge int s,int left,int right 治重新定義乙個a陣列,儲存排序完的合併陣列,void sort int s,int left,int mid,int right while i mid a k s i ...
求逆序數 逆序數 歸併排序
求排列的逆序數 分治 一 題目描述 總時間限制 1000ms 記憶體限制 65536kb 描述 在internet上的搜尋引擎經常需要對資訊進行比較,比如可以通過某個人對一些事物的排名來估計他 或她 對各種不同資訊的興趣,從而實現個性化的服務。對於不同的排名結果可以用逆序來評價它們之間的差異。考慮1...