1. 程式人生 > >根據前序遍歷和中序遍歷求後序遍歷

根據前序遍歷和中序遍歷求後序遍歷

string 第一個 tac tor att 後序 return rda post

根據前序遍歷和中序遍歷求後序遍歷

一道HULU的筆試題(How I wish yesterday once more)

假設有棵樹,長下面這個樣子,它的前序遍歷,中序遍歷,後續遍歷都很容易知道。

技術分享

PreOrder: GDAFEMHZ

InOrder: ADEFGHMZ

PostOrder: AEFDHZMG

現在,假設僅僅知道前序和中序遍歷,如何求後序遍歷呢?比如,已知一棵樹的前序遍歷是”GDAFEMHZ”,而中序遍歷是”ADEFGHMZ”應該如何求後續遍歷?

第一步,root最簡單,前序遍歷的第一節點G就是root。

第二步,繼續觀察前序遍歷GDAFEMHZ,除了知道G是root,剩下的節點必然是root的左右子樹之外,沒法找到更多信息了。

第三步,那就觀察中序遍歷ADEFGHMZ。其中root節點G左側的ADEF必然是root的左子樹,G右側的HMZ必然是root的右子樹。

第四步,觀察左子樹ADEF,左子樹的中的根節點必然是大樹的root的leftchild。在前序遍歷中,大樹的root的leftchild位於root之後,所以左子樹的根節點為D。

第五步,同樣的道理,root的右子樹節點HMZ中的根節點也可以通過前序遍歷求得。在前序遍歷中,一定是先把root和root的所有左子樹節點遍歷完之後才會遍歷右子樹,並且遍歷的右子樹的第一個節點就是右子樹的根節點。

如何知道哪裏是前序遍歷中的左子樹和右子樹的分界線呢?通過中序遍歷去數節點的個數。

在上一次中序遍歷中,root左側是A、D、E、F,所以有4個節點位於root左側。那麽在前序遍歷中,必然是第1個是G,第2到第5個由A、D、E、F過程,第6個就是root的右子樹的根節點了,是M。

第六步,觀察發現,上面的過程是遞歸的。先找到當前樹的根節點,然後劃分為左子樹,右子樹,然後進入左子樹重復上面的過程,然後進入右子樹重復上面的過程。最後就可以還原一棵樹了。

第七步,其實,如果僅僅要求寫後續遍歷,甚至不要專門占用空間保存還原後的樹。只需要稍微改動第六步,就能實現要求。僅需要把第六步的遞歸的過程改動為如下:

1 確定根,確定左子樹,確定右子樹。

2 在左子樹中遞歸。

3 在右子樹中遞歸。

4 打印當前根。

參考了一些網上的討論,具體程序是:

#include <iostream>  
#include <fstream>  
#include <string>  
  
struct TreeNode  
{  
  struct TreeNode* left;  
  struct TreeNode* right;  
  char  elem;  
};  
  
  
TreeNode* BinaryTreeFromOrderings(char* inorder, char* preorder, int length)  
{  
  if(length == 0)  
    {  
      return NULL;  
    }  
  TreeNode* node = new TreeNode;//Noice that [new] should be written out.  
  node->elem = *preorder;  
  int rootIndex = 0;  
  for(;rootIndex < length; rootIndex++)//a variation of the loop  
    {  
      if(inorder[rootIndex] == *preorder)  
      break;  
    }  
  node->left = BinaryTreeFromOrderings(inorder, preorder +1, rootIndex);  
  node->right = BinaryTreeFromOrderings(inorder + rootIndex + 1, preorder + rootIndex + 1, length - (rootIndex + 1));  
  std::cout<<node->elem<<std::endl;  
  return node;  
}  
  
int main(int argc, char** argv){  
    char* pr="GDAFEMHZ";      
 char* in="ADEFGHMZ"; BinaryTreeFromOrderings(in, pr, 8); printf("\n"); return 0;}

根據前序遍歷和中序遍歷求後序遍歷