1. 程式人生 > >逆序對個數 - 冒泡排序

逆序對個數 - 冒泡排序

col cti 一次 冒泡 UNC last version 四種 div

設一個序列為: a[0], a[1], ..., a[n-1],一個逆序對是指:{ (a[i], a[j]) | a[i] > a[j], i < j }。

統計一個序列中的逆序對個數,可以使用冒泡排序法、二路歸並法等。這裏介紹利用冒泡排序統計逆序對個數的方法。

核心思想:冒泡排序中,每進行一次交換,則序列的逆序對個數-1。

證明:設冒泡排序過程中 a[i] 與 a[i+1] 進行了一次交換,這說明 a[i] > a[i+1]。序列中逆序對可分為四種:① 非 a[i] 和非 a[i+1] 構成的逆序對;② a

[i] 和非 a[i+1] 構成的逆序對;③ a[i+1] 和非 a[i] 構成的逆序對;④ a[i] 和 a[i+1] 構成的逆序對。易知,a[i] 與 a[i+1] 交換時,①、②、③ 類型構成的逆序對個數沒變,而類型④的逆序對個數由1變為0,故每進行一次交換序列逆序對個數減少1。

冒泡排序統計逆序對的C++程序:

#include <cstdio>
#include <string>
#include <functional>
using namespace std;

/* 對T類型的數組a[lo, hi)進行排序,並返回逆序對個數。
   比較由函數對象compare實現,compare(a, b):當 a <= b,返回true。
*/ template <class T, class Comp> int countInversionBubble(T * a, int lo, int hi, Comp compare) { int n_inv = 0; // 逆序對個數 while ( lo < hi - 1 ) { int last = lo - 1; // last標示一輪氣泡中最後一次交換發生在a[i]與a[i+1]間。 for ( int i = lo; i < hi - 1; ++i ) {
if ( !compare(a[i], a[i+1]) ) { T t = a[i+1]; a[i+1] = a[i]; a[i] = t; // 交換a[i]與a[i+1] ++n_inv; last = i; } } hi = last + 1; } return n_inv; }
// 測試
int main() { int a1[] = {1}; int n1 = countInversionBubble(a1, 0, 1, less<int>()); // 0 int a2[] = {1, 2, 3}; int n2 = countInversionBubble(a2, 0, 3, less<int>()); // 0 int a3[] = {5, 4, 3, 2, 1}; int n3 = countInversionBubble(a3, 0, 5, less<int>()); // 10 int a4[] = {5, 1, 3, 2, 4}; int n4 = countInversionBubble(a4, 0, 5, less<int>()); // 5 printf("%d %d %d %d\n", n1, n2, n3, n4); return 0; }

逆序對個數 - 冒泡排序