根據二叉樹的前序走訪和中序遍曆,重構出二叉樹

來源:互聯網
上載者:User

題目:這道題目是一道面試題,先序遍曆和中序遍曆以數組的形式給出,要求我們根據這兩個條件重構出二叉樹。

是一棵二叉樹

//              6//           /     \//          5       7  //         / \       \//        2   4       8

先序遍曆:6,5,2,4,7,8

中序遍曆:2,5,4,6,7,8

思路:二叉樹先序遍曆的定義:1,先輸出根結點2,再輸出左子樹3,再輸出右子樹,因此先序遍曆時,根結點總會出現在數組開頭,中序遍曆時,根結點可以將二叉樹分為左右子樹。

因此,重構二叉樹的步驟可以用以頂向下的方法:

1,先找到根結點,

2,在中序遍曆中找到根結點位置,(可以將二叉樹分為左子樹和右子樹)

3.用同樣的辦法構造左子樹

4.用同樣的辦法構造右子樹。

例如:

1.找到根結點6,因此左子樹是2,5,4和右子樹是7,8

2.找到左邊根結點5,可將子二叉樹分為2和4,因此左邊確定。

3,找到右邊根結點7,因此可確定右子樹8。

根據四步走可以寫出如出代碼:

node* Build_Tree(int* prec,int* inorder,int len){//步驟1:建立根結點node* root=new node(prec[0]);//步驟2:在中序遍曆中找到根結點索引,分割左右子樹int SubTreeLen=0;while(SubTreeLen < len && inorder[SubTreeLen] != prec[0])++SubTreeLen;if(SubTreeLen > 0){//步驟2:重建左子樹,並且將根結點root的left指向左子樹root->left=Build_Tree(prec+1,inorder,SubTreeLen);}if(len-SubTreeLen-1 > 0){//步驟2:重建右子樹,並且將根結點root的left指向右子樹root->right=Build_Tree(prec+1+SubTreeLen,inorder+1+SubTreeLen,len-SubTreeLen-1);}return root;}

接下來的步驟就是進行程式測試,利用邊界值等去測試程式的健壯性。

可以利用下面的二叉樹去測試:

// 普通二叉樹//              1//           /     \//          2       3  //         /       / \//        4       5   6//         \         ///          7       8int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};// 所有結點都沒有右子結點//            1//           / //          2   //         / //        3 //       ///      4//     ///    5int preorder[length] = {1, 2, 3, 4, 5};int inorder[length] = {5, 4, 3, 2, 1};// 所有結點都沒有左子結點//            1//             \ //              2   //               \ //                3 //                 \//                  4//                   \//                    5int preorder[length] = {1, 2, 3, 4, 5};int inorder[length] = {1, 2, 3, 4, 5};// 樹中只有一個結點    int preorder[length] = {1};    int inorder[length] = {1};// 完全二叉樹//              1//           /     \//          2       3  //         / \     / \//        4   5   6   7    int preorder[length] = {1, 2, 4, 5, 3, 6, 7};    int inorder[length] = {4, 2, 5, 1, 6, 3, 7};// 輸入null 指標// 輸入的兩個序列不匹配    int preorder[length] = {1, 2, 4, 5, 3, 6, 7};    int inorder[length] = {4, 2, 8, 1, 6, 3, 7};

上述測試例子引自於:《劍指Offer——名企面試官精講典型編程題》

經過測試,當輸入null 指標和兩個序列不匹配時,原始的程式無辦法處理,可以針對性處理如下:

#include<iostream>#include <exception>using std::cout;using std::endl;struct node{int value;node* left;node* right;node(int v):value(v),left(NULL),right(NULL){}};node* Build_Tree(int* prec,int* inorder,int len){if(!prec || !inorder || len <=0 ){cout<<"Empty Input!"<<endl;exit(1);//暴力關機}//步驟1:建立根結點node* root=new node(prec[0]);//步驟2:在中序遍曆中找到根結點索引,分割左右子樹int SubTreeLen=0;while(SubTreeLen < len && inorder[SubTreeLen] != prec[0])++SubTreeLen;if(SubTreeLen == len)//越界了,說明兩個數組無法構造出二叉樹{cout<<"Wrong Input!"<<endl;exit(1);//暴力關機}if(SubTreeLen > 0){//步驟2:重建左子樹,並且將根結點root的left指向左子樹root->left=Build_Tree(prec+1,inorder,SubTreeLen);}if(len-SubTreeLen-1 > 0){//步驟2:重建右子樹,並且將根結點root的left指向右子樹root->right=Build_Tree(prec+1+SubTreeLen,inorder+1+SubTreeLen,len-SubTreeLen-1);}return root;}void prec_tree_walk(node* z){if(!z)return ;cout<<z->value<<' ';prec_tree_walk(z->left);prec_tree_walk(z->right);}void inorder_tree_walk(node* z){if(!z)return ;inorder_tree_walk(z->left);cout<<z->value<<' ';inorder_tree_walk(z->right);}int main(){int prec[] = {1, 2, 4, 7, 3, 5, 6, 8};int Inorder[] = {4, 7, 2, 1, 5, 3, 8, 6};int len=sizeof(prec)/sizeof(prec[0]);node* root=Build_Tree(prec,Inorder,len);prec_tree_walk(root);cout<<endl;inorder_tree_walk(root);return 0;}

中途發現的編譯錯誤記錄如下:點擊開啟連結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.