• [刷题] 剑指Offer 面试题7:重建二叉树


    题目:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树。(假设输入的前序和中序遍历结果中都不含重复数字)

    思路

    • 构建二叉树的两个函数:Construct()、ConstructCore()
    • Construct()面向输入数据(用户),ConstructCore()面向处理数据(程序)
    • 通过Construct()调用ConstructCore(),对用户隐藏了具体实现
      1 #include "BinaryTree.h"
      2 #include <stdexcept>
      3 #include <iostream>
      4 #include <cstdio>
      5 #include <cstdlib>
      6 
      7 BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);
      8 
      9 BinaryTreeNode* Construct(int* preorder, int* inorder, int length)
     10 {
     11     if(preorder == nullptr || inorder == nullptr || length <= 0)
     12         return nullptr;
     13 
     14     return ConstructCore(preorder, preorder + length - 1,
     15         inorder, inorder + length - 1);
     16 }
     17 
     18 BinaryTreeNode* ConstructCore
     19 (
     20     int* startPreorder, int* endPreorder, 
     21     int* startInorder, int* endInorder
     22 )
     23 {
     24     // 前序遍历序列的第一个数字是根结点的值
     25     int rootValue = startPreorder[0];
     26     BinaryTreeNode* root = new BinaryTreeNode();
     27     root->m_nValue = rootValue;
     28     root->m_pLeft = root->m_pRight = nullptr;
     29 
     30     if(startPreorder == endPreorder)
     31     {
     32         if(startInorder == endInorder && *startPreorder == *startInorder)
     33             return root;
     34         else
     35             throw -1;
     36     }
     37 
     38     // 在中序遍历中找到根结点的值
     39     int* rootInorder = startInorder;
     40     while(rootInorder <= endInorder && *rootInorder != rootValue)
     41         ++ rootInorder;
     42 
     43     if(rootInorder == endInorder && *rootInorder != rootValue)
     44         throw -1;
     45 
     46     int leftLength = rootInorder - startInorder;
     47     int* leftPreorderEnd = startPreorder + leftLength;
     48     if(leftLength > 0)
     49     {
     50         // 构建左子树
     51         root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, 
     52             startInorder, rootInorder - 1);
     53     }
     54     if(leftLength < endPreorder - startPreorder)
     55     {
     56         // 构建右子树
     57         root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
     58             rootInorder + 1, endInorder);
     59     }
     60 
     61     return root;
     62 }
     63 
     64 // ====================测试代码====================
     65 void Test(char* testName, int* preorder, int* inorder, int length)
     66 {
     67     if(testName != nullptr)
     68         printf("%s begins:
    ", testName);
     69 
     70     printf("The preorder sequence is: ");
     71     for(int i = 0; i < length; ++ i)
     72         printf("%d ", preorder[i]);
     73     printf("
    ");
     74 
     75     printf("The inorder sequence is: ");
     76     for(int i = 0; i < length; ++ i)
     77         printf("%d ", inorder[i]);
     78     printf("
    ");
     79 
     80     try
     81     {
     82         BinaryTreeNode* root = Construct(preorder, inorder, length);
     83         PrintTree(root);
     84         DestroyTree(root);
     85     }
     86     catch(int d)
     87     {
     88         printf("Invalid Input.
    ");
     89     }
     90 }
     91 
     92 // 普通二叉树
     93 //              1
     94 //           /     
     95 //          2       3  
     96 //         /       / 
     97 //        4       5   6
     98 //                  /
     99 //          7       8
    100 void Test1()
    101 {
    102     const int length = 8;
    103     int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};
    104     int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};
    105 
    106     Test("Test1", preorder, inorder, length);
    107 }
    108 
    109 // 所有结点都没有右子结点
    110 //            1
    111 //           / 
    112 //          2   
    113 //         / 
    114 //        3 
    115 //       /
    116 //      4
    117 //     /
    118 //    5
    119 void Test2()
    120 {
    121     const int length = 5;
    122     int preorder[length] = {1, 2, 3, 4, 5};
    123     int inorder[length] = {5, 4, 3, 2, 1};
    124 
    125     Test("Test2", preorder, inorder, length);
    126 }
    127 
    128 // 所有结点都没有左子结点
    129 //            1
    130 //              
    131 //              2   
    132 //                
    133 //                3 
    134 //                 
    135 //                  4
    136 //                   
    137 //                    5
    138 void Test3()
    139 {
    140     const int length = 5;
    141     int preorder[length] = {1, 2, 3, 4, 5};
    142     int inorder[length] = {1, 2, 3, 4, 5};
    143 
    144     Test("Test3", preorder, inorder, length);
    145 }
    146 
    147 // 树中只有一个结点
    148 void Test4()
    149 {
    150     const int length = 1;
    151     int preorder[length] = {1};
    152     int inorder[length] = {1};
    153 
    154     Test("Test4", preorder, inorder, length);
    155 }
    156 
    157 // 完全二叉树
    158 //              1
    159 //           /     
    160 //          2       3  
    161 //         /      / 
    162 //        4   5   6   7
    163 void Test5()
    164 {
    165     const int length = 7;
    166     int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
    167     int inorder[length] = {4, 2, 5, 1, 6, 3, 7};
    168 
    169     Test("Test5", preorder, inorder, length);
    170 }
    171 
    172 // 输入空指针
    173 void Test6()
    174 {
    175     Test("Test6", nullptr, nullptr, 0);
    176 }
    177 
    178 // 输入的两个序列不匹配
    179 void Test7()
    180 {
    181     const int length = 7;
    182     int preorder[length] = {1, 2, 4, 5, 3, 6, 7};
    183     int inorder[length] = {4, 2, 8, 1, 6, 3, 7};
    184     Test("Test7: for unmatched input", preorder, inorder, length);
    185 }
    186 
    187 int main(int argc, char* argv[])
    188 {
    189     Test1();
    190     Test2();
    191     Test3();
    192     Test4();
    193     Test5();
    194     Test6();
    195     Test7();
    196     return 0;
    197 }

                 

    BinaryTree.cpp

     1 #include <cstdio>
     2 #include "BinaryTree.h"
     3 
     4 BinaryTreeNode* CreateBinaryTreeNode(int value)
     5 {
     6     BinaryTreeNode* pNode = new BinaryTreeNode();
     7     pNode->m_nValue = value;
     8     pNode->m_pLeft = nullptr;
     9     pNode->m_pRight = nullptr;
    10 
    11     return pNode;
    12 }
    13 
    14 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
    15 {
    16     if(pParent != nullptr)
    17     {
    18         pParent->m_pLeft = pLeft;
    19         pParent->m_pRight = pRight;
    20     }
    21 }
    22 
    23 void PrintTreeNode(const BinaryTreeNode* pNode)
    24 {
    25     if(pNode != nullptr)
    26     {
    27         printf("value of this node is: %d
    ", pNode->m_nValue);
    28 
    29         if(pNode->m_pLeft != nullptr)
    30             printf("value of its left child is: %d.
    ", pNode->m_pLeft->m_nValue);
    31         else
    32             printf("left child is nullptr.
    ");
    33 
    34         if(pNode->m_pRight != nullptr)
    35             printf("value of its right child is: %d.
    ", pNode->m_pRight->m_nValue);
    36         else
    37             printf("right child is nullptr.
    ");
    38     }
    39     else
    40     {
    41         printf("this node is nullptr.
    ");
    42     }
    43 
    44     printf("
    ");
    45 }
    46 
    47 void PrintTree(const BinaryTreeNode* pRoot)
    48 {
    49     PrintTreeNode(pRoot);
    50 
    51     if(pRoot != nullptr)
    52     {
    53         if(pRoot->m_pLeft != nullptr)
    54             PrintTree(pRoot->m_pLeft);
    55 
    56         if(pRoot->m_pRight != nullptr)
    57             PrintTree(pRoot->m_pRight);
    58     }
    59 }
    60 
    61 void DestroyTree(BinaryTreeNode* pRoot)
    62 {
    63     if(pRoot != nullptr)
    64     {
    65         BinaryTreeNode* pLeft = pRoot->m_pLeft;
    66         BinaryTreeNode* pRight = pRoot->m_pRight;
    67 
    68         delete pRoot;
    69         pRoot = nullptr;
    70 
    71         DestroyTree(pLeft);
    72         DestroyTree(pRight);
    73     }
    74 }

    BinaryTree.h

     1 struct BinaryTreeNode 
     2 {
     3     int                    m_nValue; 
     4     BinaryTreeNode*        m_pLeft;  
     5     BinaryTreeNode*        m_pRight; 
     6 };
     7 
     8 BinaryTreeNode* CreateBinaryTreeNode(int value);
     9 void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight);
    10 void PrintTreeNode(const BinaryTreeNode* pNode);
    11 void PrintTree(const BinaryTreeNode* pRoot);
    12 void DestroyTree(BinaryTreeNode* pRoot);

     参考:

    https://github.com/cxc1357/CodingInterviewChinese2

  • 相关阅读:
    【核心算法1】双指针问题
    关于博客园主题
    正交工具allpairs使用
    postman设置变量
    WebDriver驱动下载地址
    MySQL语法基础
    异或
    测试——pytest库上手
    and 和 or 的语句运算
    爬虫——Scrapy中选择器的基本使用(转)
  • 原文地址:https://www.cnblogs.com/cxc1357/p/12014209.html
Copyright © 2020-2023  润新知