對錦標賽演算法與完美洗牌的分析

2021-07-25 07:04:11 字數 2215 閱讀 3340

如果要在n個資料中挑選出第一大和第二大的資料(要求輸出資料所在位置和值),使用什麼方法比較的次數最少?我們可以從體育錦標賽中受到啟發。

如圖【1.png】所示,8個選手的錦標賽,先兩兩捉對比拼,淘汰一半。優勝者再兩兩比拼…直到決出第一名。

第一名輸出後,只要對黃色標示的位置重新比賽即可。

下面的**實現了這個演算法(假設資料中沒有相同值)。

**中需要用乙個陣列來表示圖中的樹(注意,這是個滿二叉樹,不足需要補齊)。它不是儲存資料本身,而是儲存了資料的下標。

第乙個資料輸出後,它所在的位置被標識為-1 

藍橋杯上的乙個填空題,感覺想法很好。 

用乙個b陣列來存放這些數的下標,為空的地方就賦值為-1,然後通過左右子樹不斷的比較,將大數放到父親節點,一直到根節點,先輸出最大數,然後進行第二次比較,從根節點一直往下,把較大的數繼續放到父親節點,把第一次的最大數覆蓋,一直到根節點,再輸出第二大的數。 

**如下:

#include

#include

#include

using

namespace

std;

void pk(int* a, int* b, int n, int k, int v)

if(b[k1]==v)

pk(a,b,n,k1,v);

else

pk(a,b,n,k2,v);

//重新比較

if(b[k1]<0)

if(b[k2]<0)

if(a[b[k1]]>a[b[k2]]) //填空

b[k] = b[k1];

else

b[k] = b[k2];

}//對a中資料,輸出最大,次大元素位置和值

void f(int* a, int len)

//從最後乙個向前處理

for(i=2*n-1-1; i>0; i-=2)

else

}//輸出樹根

printf("%d : %d\n", b[0], a[b[0]]);

//值等於根元素的需要重新pk

pk(a,b,2*n-1,0,b[0]);

//再次輸出樹根

printf("%d : %d\n", b[0], a[b[0]]);

free(b);

}int main()

; f(a,9);

}a1, a2,a3,a4,b1,b2,b3,b4

我們先要把前半段的後2個元素(a3,a4)與後半段的前2個元素(b1,b2)交換,得到a1,a2,b1,b2,a3,a4,b3,b4。

於是,我們分別求解子問題a (a1,a2,b1,b2)和子問題b (a3,a4,b3,b4)就可以了。

如果n = 5,是偶數怎麼辦?我們原始的陣列是a1,a2,a3,a4,a5,b1,b2,b3,b4,b5,我們先把a5拎出來,後面所有元素前移,再把a5放到最後,變為a1,a2,a3,a4,b1,b2,b3,b4,b5,a5。可見這時最後兩個元素b5,a5已經是我們要的結果了,所以我們只要考慮n=4就可以了。

那麼複雜度怎麼算? 每次,我們交換中間的n個元素,需要o(n)的時間,n是奇數的話,我們還需要o(n)的時間先把後兩個元素調整好,但這步影響總體時間複雜度。所以,無論如何都是o(n)的時間複雜度。

於是我們有 t(n) = t(n / 2) + o(n)  這個就是跟歸併排序一樣的複雜度式子,最終複雜度解出來t(n) = o(nlogn)。空間的話,我們就在陣列內部折騰的,所以是o(1)。(當然沒有考慮遞迴的棧的空間)

**://時間o(nlogn) 空間o(1) 陣列下標從1開始

void perfect_shuffle2(int *a,int n)

int n2 = n * 2, n3 = n / 2;

if (n % 2 == 1)

a[n2] = t;

--n;

} //到此n是偶數

for (i = n3 + 1; i <= n; ++i)

// [1.. n /2]

perfect_shuffle2(a, n3);

perfect_shuffle2(a + n, n3);

}

錦標賽排序演算法 java版

今天在做遊戲的聯賽系統,假如有n 人報名參加聯賽,伺服器記錄下報名人數,並對這些人的戰鬥後的結果進行排序,決出前16強或者8強。網上找了下錦標賽排序演算法,內容真少。總結下 1 建樹 這裡說的建樹是建立一顆完全二叉樹。當參加排序的陣列不足2的n次冪,將其補足。直到滿足建立乙個完全二叉樹 2 當某結點...

演算法 排序(2)錦標賽排序

用完全二叉樹定義勝者樹,前n 1個結點t 1 t n 1 為內部結點 勝者 後n個結點e 1 e n 是參賽者。t陣列存的是參賽者編號,即e t 0 才是最終勝者的值 t 1 並沒有改變 int winner const int winner int i const int winner int a...

錦標賽問題 遞迴

設有n位選手參加網球迴圈賽,n 2 k,迴圈賽共進行n 1天,每位選手要與其他n 1位選手比賽一場,且每位選手每天比賽一場,不能輪空,按一下要求為比賽安排日程,1 每位選手必須與其他n 1格選手格賽一場 2 每個選手每天只能賽一場 3 迴圈賽一共進行n 1天 請按此要求將比賽日程表設計成有n行和n ...