国产18禁黄网站免费观看,99爱在线精品免费观看,粉嫩metart人体欣赏,99久久99精品久久久久久,6080亚洲人久久精品

2015年軟件水平考試精選題(4)

時間:2015-04-02 15:57:00   來源:無憂考網     [字體: ]
求二元查找樹的鏡像

  題目:輸入一顆二元查找樹,將該樹轉換為它的鏡像,即在轉換后的二元查找樹中,左子樹的結點都大于右子樹的結點。用遞歸和循環(huán)兩種方法完成樹的鏡像轉換。

  例如輸入:

  8

  / \

  6 10

  /\ /\

  5 7 9 11

  輸出:

  8

  / \

  10 6

  /\ /\

  11 9 7 5

  定義二元查找樹的結點為:

  struct BSTreeNode // a node in the binary search tree (BST)

  {

  int m_nValue; // value of node

  BSTreeNode *m_pLeft; // left child of node

  BSTreeNode *m_pRight; // right child of node

  };

  分析:盡管我們可能一下子不能理解鏡像是什么意思,但上面的例子給我們的直觀感覺,就是交換結點的左右子樹。我們試著在遍歷例子中的二元查找樹的同時來交換每個結點的左右子樹。遍歷時首先訪問頭結點8,我們交換它的左右子樹得到:

  8

  / \

  10 6

  /\ /\

  9 11 5 7

  我們發(fā)現兩個結點6和10的左右子樹仍然是左結點的值小于右結點的值,我們再試著交換他們的左右子樹,得到:

  8

  / \

  10 6

  /\ /\

  11 9 7 5

  剛好就是要求的輸出。

  上面的分析印證了我們的直覺:在遍歷二元查找樹時每訪問到一個結點,交換它的左右子樹。這種思路用遞歸不難實現,將遍歷二元查找樹的代碼稍作修改就可以了。參考代碼如下:

  ///////////////////////////////////////////////////////////////////////

  // Mirror a BST (swap the left right child of each node) recursively

  // the head of BST in initial call

  ///////////////////////////////////////////////////////////////////////

  void MirrorRecursively(BSTreeNode *pNode)

  {

  if(!pNode)

  return;

  // swap the right and left child sub-tree

  BSTreeNode *pTemp = pNode->m_pLeft;

  pNode->m_pLeft = pNode->m_pRight;

  pNode->m_pRight = pTemp;

  // mirror left child sub-tree if not null

  if(pNode->m_pLeft)

  MirrorRecursively(pNode->m_pLeft);

  // mirror right child sub-tree if not null

  if(pNode->m_pRight)

  MirrorRecursively(pNode->m_pRight);

  }

  由于遞歸的本質是編譯器生成了一個函數調用的棧,因此用循環(huán)來完成同樣任務時最簡單的辦法就是用一個輔助棧來模擬遞歸。首先我們把樹的頭結點放入棧中。在循環(huán)中,只要棧不為空,彈出棧的棧頂結點,交換它的左右子樹。如果它有左子樹,把它的左子樹壓入棧中;如果它有右子樹,把它的右子樹壓入棧中。這樣在下次循環(huán)中就能交換它兒子結點的左右子樹了。參考代碼如下:

  ///////////////////////////////////////////////////////////////////////

  // Mirror a BST (swap the left right child of each node) Iteratively

  // Input: pTreeHead: the head of BST

  ///////////////////////////////////////////////////////////////////////

  void MirrorIteratively(BSTreeNode *pTreeHead)

  {

  if(!pTreeHead)

  return;

  std::stackstackTreeNode;

  stackTreeNode.push(pTreeHead);

  while(stackTreeNode.size())

  {

  BSTreeNode *pNode = stackTreeNode.top();

  stackTreeNode.pop();

  // swap the right and left child sub-tree

  BSTreeNode *pTemp = pNode->m_pLeft;

  pNode->m_pLeft = pNode->m_pRight;

  pNode->m_pRight = pTemp;

  // push left child sub-tree into stack if not null

  if(pNode->m_pLeft)

  stackTreeNode.push(pNode->m_pLeft);

  // push right child sub-tree into stack if not null

  if(pNode->m_pRight)

  stackTreeNode.push(pNode->m_pRight);

  }

  }
 從上往下遍歷二元樹

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

  例如輸入

  8

  / \

  6 10

  /\ /\

  5 7 9 11

  輸出8 6 10 5 7 9 11。

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

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

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

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

  參考代碼:

  #include

  #include

  using namespace std;

  struct BTreeNode // a node in the binary tree

  {

  int m_nValue; // value of node

  BTreeNode *m_pLeft; // left child of node

  BTreeNode *m_pRight; // right child 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 a empty queue

  deque dequeTreeNode;

  // insert the root at the tail of queue

  dequeTreeNode.push_back(pTreeRoot);

  while(dequeTreeNode.size())

  {

  // get a node from the head of queue

  BTreeNode *pNode = dequeTreeNode.front();

  dequeTreeNode.pop_front();

  // print the node

  cout << pNode->m_nValue << ' ';

  // print its left child sub-tree if it has

  if(pNode->m_pLeft)

  dequeTreeNode.push_back(pNode->m_pLeft);

  // print its right child sub-tree if it has

  if(pNode->m_pRight)

  dequeTreeNode.push_back(pNode->m_pRight);

  }

  }