摘要:求二元查找樹的鏡像 題目:輸入一顆二元查找樹,將該樹轉換為它的鏡像,即在轉換后的二元查找樹中,左子樹的結點都大于右子樹的結點。用遞歸和循環(huán)兩種方法完成樹的鏡像轉換。
點擊進入>>>>>
求二元查找樹的鏡像
題目:輸入一顆二元查找樹,將該樹轉換為它的鏡像,即在轉換后的二元查找樹中,左子樹的結點都大于右子樹的結點。用遞歸和循環(huán)兩種方法完成樹的鏡像轉換。
例如輸入:
8
/\
610
/\/\
57911
輸出:
8
/\
106
/\/\
11975
定義二元查找樹的結點為:
structBSTreeNode//anodeinthebinarysearchtree(BST)
{
intm_nValue;//valueofnode
BSTreeNode*m_pLeft;//leftchildofnode
BSTreeNode*m_pRight;//rightchildofnode
};
分析:盡管我們可能一下子不能理解鏡像是什么意思,但上面的例子給我們的直觀感覺,就是交換結點的左右子樹。我們試著在遍歷例子中的二元查找樹的同時來交換每個結點的左右子樹。遍歷時首先訪問頭結點8,我們交換它的左右子樹得到:
8
/\
106
/\/\
91157
我們發(fā)現(xiàn)兩個結點6和10的左右子樹仍然是左結點的值小于右結點的值,我們再試著交換他們的左右子樹,得到:
8
/\
106
/\/\
11975
剛好就是要求的輸出。
上面的分析印證了我們的直覺:在遍歷二元查找樹時每訪問到一個結點,交換它的左右子樹。這種思路用遞歸不難實現(xiàn),將遍歷二元查找樹的代碼稍作修改就可以了。參考代碼如下:
///////////////////////////////////////////////////////////////////////
//MirroraBST(swaptheleftrightchildofeachnode)recursively
//theheadofBSTininitialcall
///////////////////////////////////////////////////////////////////////
voidMirrorRecursively(BSTreeNode*pNode)
{
if(!pNode)
return;
//swaptherightandleftchildsub-tree
BSTreeNode*pTemp=pNode->m_pLeft;
pNode->m_pLeft=pNode->m_pRight;
pNode->m_pRight=pTemp;
//mirrorleftchildsub-treeifnotnull
if(pNode->m_pLeft)
MirrorRecursively(pNode->m_pLeft);
//mirrorrightchildsub-treeifnotnull
if(pNode->m_pRight)
MirrorRecursively(pNode->m_pRight);
}
由于遞歸的本質是編譯器生成了一個函數(shù)調用的棧,因此用循環(huán)來完成同樣任務時最簡單的辦法就是用一個輔助棧來模擬遞歸。首先我們把樹的頭結點放入棧中。在循環(huán)中,只要棧不為空,彈出棧的棧頂結點,交換它的左右子樹。如果它有左子樹,把它的左子樹壓入棧中;如果它有右子樹,把它的右子樹壓入棧中。這樣在下次循環(huán)中就能交換它兒子結點的左右子樹了。參考代碼如下:
///////////////////////////////////////////////////////////////////////
//MirroraBST(swaptheleftrightchildofeachnode)Iteratively
//Input:pTreeHead:theheadofBST
///////////////////////////////////////////////////////////////////////
voidMirrorIteratively(BSTreeNode*pTreeHead)
{
if(!pTreeHead)
return;
std::stackstackTreeNode;
stackTreeNode.push(pTreeHead);
while(stackTreeNode.size())
{
BSTreeNode*pNode=stackTreeNode.top();
stackTreeNode.pop();
//swaptherightandleftchildsub-tree
BSTreeNode*pTemp=pNode->m_pLeft;
pNode->m_pLeft=pNode->m_pRight;
pNode->m_pRight=pTemp;
//pushleftchildsub-treeintostackifnotnull
if(pNode->m_pLeft)
stackTreeNode.push(pNode->m_pLeft);
//pushrightchildsub-treeintostackifnotnull
if(pNode->m_pRight)
stackTreeNode.push(pNode->m_pRight);
}
}
從上往下遍歷二元樹
題目:輸入一顆二元樹,從上往下按層打印樹的每個結點,同一層中按照從左往右的順序打印。
例如輸入
8
/\
610
/\/\
57911
輸出861057911。
分析:這曾是微軟的一道面試題。這道題實質上是要求遍歷一棵二元樹,只不過不是我們熟悉的前序、中序或者后序遍歷。
我們從樹的根結點開始分析。自然先應該打印根結點8,同時為了下次能夠打印8的兩個子結點,我們應該在遍歷到8時把子結點6和10保存到一個數(shù)據(jù)容器中?,F(xiàn)在數(shù)據(jù)容器中就有兩個元素6和10了。按照從左往右的要求,我們先取出6訪問。打印6的同時要把6的兩個子結點5和7放入數(shù)據(jù)容器中,此時數(shù)據(jù)容器中有三個元素10、5和7。接下來我們應該從數(shù)據(jù)容器中取出結點10訪問了。注意10比5和7先放入容器,此時又比5和7先取出,就是我們通常說的先入先出。因此不難看出這個數(shù)據(jù)容器的類型應該是個隊列。
既然已經(jīng)確定數(shù)據(jù)容器是一個隊列,現(xiàn)在的問題變成怎么實現(xiàn)隊列了。實際上我們無需自己動手實現(xiàn)一個,因為STL已經(jīng)為我們實現(xiàn)了一個很好的deque(兩端都可以進出的隊列),我們只需要拿過來用就可以了。
我們知道樹是圖的一種特殊退化形式。同時如果對圖的深度優(yōu)先遍歷和廣度優(yōu)先遍歷有比較深刻的理解,將不難看出這種遍歷方式實際上是一種廣度優(yōu)先遍歷。因此這道題的本質是在二元樹上實現(xiàn)廣度優(yōu)先遍歷。
參考代碼:
#include
#include
usingnamespacestd;
structBTreeNode//anodeinthebinarytree
{
intm_nValue;//valueofnode
BTreeNode*m_pLeft;//leftchildofnode
BTreeNode*m_pRight;//rightchildofnode
};
///////////////////////////////////////////////////////////////////////
//Printabinarytreefromtopleveltobottomlevel
//Input:pTreeRoot-therootofbinarytree
///////////////////////////////////////////////////////////////////////
voidPrintFromTopToBottom(BTreeNode*pTreeRoot)
{
if(!pTreeRoot)
return;
//getaemptyqueue
dequedequeTreeNode;
//inserttherootatthetailofqueue
dequeTreeNode.push_back(pTreeRoot);
while(dequeTreeNode.size())
{
//getanodefromtheheadofqueue
BTreeNode*pNode=dequeTreeNode.front();
dequeTreeNode.pop_front();
//printthenode
cout<<pNode->m_nValue<<'';
//printitsleftchildsub-treeifithas
if(pNode->m_pLeft)
dequeTreeNode.push_back(pNode->m_pLeft);
//printitsrightchildsub-treeifithas
if(pNode->m_pRight)
dequeTreeNode.push_back(pNode->m_pRight);
}
}
相關推薦:
軟考備考資料免費領取
去領取