1. 程式人生 > >程式設計師面試寶典(12)-從上往下遍歷二元樹

程式設計師面試寶典(12)-從上往下遍歷二元樹

http://www.itmian4.com/thread-6009-1-1.html

題目:輸入一顆二元樹,從上往下按層列印樹的每個結點,同一層中按照從左往右的順序列印。

例如輸入         

      8
    / \
   6   10
  /\     /\
5 7   9  11

輸出8   6   10  5   7   9   11。

分析:這曾是微軟的一道面試題。這道題實質上是要求遍歷一棵二元樹,只不過不是我們熟悉的前序、中序或者後序遍歷。

我們從樹的根結點開始分析。自然先應該列印根結點8,同時為了下次能夠列印8的兩個子結點,我們應該在遍歷到8時把子結點6和10儲存到一個數據容器中。現在資料容器中就有兩個元素6 和10了。按照從左往右的要求,我們先取出6訪問。列印6的同時要把6的兩個子結點5和7放入資料容器中,此時資料容器中有三個元素10、5和7。接下來我們應該從資料容器中取出結點10訪問了。注意10比5和7先放入容器,此時又比5和7先取出,就是我們通常說的先入先出。因此不難看出這個資料容器的型別應該是個佇列。

既然已經確定資料容器是一個佇列,現在的問題變成怎麼實現隊列了。實際上我們無需自己動手實現一個,因為STL已經為我們實現了一個很好的deque(兩端都可以進出的佇列),我們只需要拿過來用就可以了。

我們知道樹是圖的一種特殊退化形式。同時如果對圖的深度優先遍歷和廣度優先遍歷有比較深刻的理解,將不難看出這種遍歷方式實際上是一種廣度優先遍歷。因此這道題的本質是在二元樹上實現廣度優先遍歷。

參考程式碼:

#include <deque>
#include <iostream>
using namespacestd;

struct BTreeNode // anode in the binary tree
{
    int         m_nValue; //value of node
    BTreeNode  *m_pLeft; // left child of node
    BTreeNode  *m_pRight; // rightchild of node
};

///////////////////////////////////////////////////////////////////////
// Print a binary tree from top level to bottom level
// Input: pTreeRoot - the root of binary tree
///////////////////////////////////////////////////////////////////////
void PrintFromTopToBottom(BTreeNode*pTreeRoot)
{
    if(!pTreeRoot)
       return;

    // get aempty queue
    deque<BTreeNode *>dequeTreeNode;

    // insertthe root at the tail of queue
    dequeTreeNode.push_back(pTreeRoot);

    while(dequeTreeNode.size())
    {
       // get anode from the head of queue
       BTreeNode *pNode =dequeTreeNode.front();
       dequeTreeNode.pop_front();

       // printthe node
       cout <<pNode->m_nValue << ' ';

       // printits left child sub-tree if it has
       if(pNode->m_pLeft)
           dequeTreeNode.push_back(pNode->m_pLeft);
       // printits right child sub-tree if it has
       if(pNode->m_pRight)
           dequeTreeNode.push_back(pNode->m_pRight);
    }
}