二叉树小球下落问题c语言,#C++初学记录(树和二叉树)
二叉樹的編號(hào) 例題 6-6 小球下落問題 有一棵二叉樹,最大深度為D,且所有葉子深度都相同。所有節(jié)點(diǎn)從上到下,從左到右編號(hào)為1,2,3,4,....,2^D-1。在節(jié)點(diǎn)1處放置小球,他會(huì)往下落。每個(gè)節(jié)點(diǎn)上都有一個(gè)開關(guān),初始全部關(guān)閉,每當(dāng)有小球落到一個(gè)開關(guān)上時(shí),狀態(tài)都會(huì)改變,當(dāng)一個(gè)小球到達(dá)節(jié)點(diǎn)時(shí),如果該節(jié)點(diǎn)上的開關(guān)關(guān)閉則往左走,否則往右走,直到走到葉子節(jié)點(diǎn),一些小球從節(jié)點(diǎn)1處開始依次下落。最后一個(gè)小球回到哪里呢?輸入葉子深度D,小球個(gè)數(shù)I,輸入第I個(gè)小球最后所在的葉子編號(hào)。假設(shè)I不超過整棵樹的葉子個(gè)數(shù),D<=20。輸入最多包含1000組數(shù)據(jù)。 **get ** 4 2 3 4 10 1 2 2 8 128 16 12345 put 12 7 512 3 255 36358
#include
#include
const int maxd=20;
int s[1<
int main()
{
int D,I;
while((cin>>D>>I)==2)
{
memset(s,0,sizeof(s));
int k=1,n=(1<
for(int i=0;i
{
k=1;
for(;;;)
{
s[k]=!s[k];
k=s[k]?2*k:2*k+1;
if(k>n)break;
}
}
cout<
}
return 0;
}
代碼非常基礎(chǔ)不難理解,用k表示小球現(xiàn)在所在的節(jié)點(diǎn)位置再進(jìn)行判斷是否出界出界則跳出循環(huán)后進(jìn)行下一步循環(huán)并且對(duì)k進(jìn)行初始化,直到循環(huán)結(jié)束即第I個(gè)小球下落到底。
但是,這樣做的代碼有一個(gè)明顯的缺陷,那就是時(shí)間復(fù)雜度問題,運(yùn)算量太大,由于I可以高達(dá)2^D-1,每組測(cè)試數(shù)據(jù)下落總層數(shù)可能會(huì)高達(dá)(2^19)*19=9961472,并且一共可能有10000組數(shù)據(jù)。 還有一種方法我們可以這樣理解,每個(gè)小球都會(huì)落到根節(jié)點(diǎn)上,并且前兩個(gè)小球一定必然是一個(gè)落在左邊子樹上一個(gè)落在右邊子樹上,一般的,只需要看小球編號(hào)的奇偶性,就能直到他最終會(huì)在那棵子樹中,對(duì)于那些落入根節(jié)點(diǎn)左子樹的小球來說,只需要知道該小球是第幾個(gè)落在根的左子樹,就可以直到他下一步往左還是往右了,依次類推,直到小球落到葉子上為止。 如果使用題目中給的編號(hào)I,則當(dāng)I是奇數(shù)時(shí),他是往左走的第(I+1)/2個(gè)小球,當(dāng)I是偶數(shù)時(shí),他是往右走的第I/2個(gè)小球。這樣,可以直接模擬最后一個(gè)小球的路線,實(shí)現(xiàn)代碼:
while((cin>>D>>I)==2)
{
int k=1;
for(int i=0;i
if(I%2){
k=k*2;
I=(I+1)/2;
}
else
{
k=k*2+1;
I/=2;
}
cout<
}
總結(jié)
以上是生活随笔為你收集整理的二叉树小球下落问题c语言,#C++初学记录(树和二叉树)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux的Vi命令详解
- 下一篇: C++ 解析Json