如果要在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 ...