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

思路

  • 构建二叉树的两个函数: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:\n", testName);
69
70 printf("The preorder sequence is: ");
71 for(int i = 0; i < length; ++ i)
72 printf("%d ", preorder[i]);
73 printf("\n");
74
75 printf("The inorder sequence is: ");
76 for(int i = 0; i < length; ++ i)
77 printf("%d ", inorder[i]);
78 printf("\n");
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.\n");
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\n", pNode->m_nValue);
28
29 if(pNode->m_pLeft != nullptr)
30 printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
31 else
32 printf("left child is nullptr.\n");
33
34 if(pNode->m_pRight != nullptr)
35 printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
36 else
37 printf("right child is nullptr.\n");
38 }
39 else
40 {
41 printf("this node is nullptr.\n");
42 }
43
44 printf("\n");
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

[刷题] 剑指Offer 面试题7:重建二叉树的更多相关文章

  1. 剑指offer面试题6 重建二叉树(c)

  2. 剑指offer面试题6 重建二叉树(java)

    注:(1)java中树的构建 (2)构建子树时可以直接利用Arrays.copyOfRange(preorder, from, to),这个方法是左开右闭的 package com.xsf.SordF ...

  3. [刷题] 剑指offer 面试题18:删除链表节点

    要求 给定单向链表的头指针和一个节点指针,在O(1)时间内删除该节点 常规思路:从头节点a开始顺序遍历,发现p指向要删除的节点i,然后把p的m_pNext指向i的下一个节点j,时间复杂度O(n) O( ...

  4. 剑指Offer:面试题6——重建二叉树(java实现)

    问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不包含重复的数字. 例如: 输入:前序{1,2,4,7,3,5,6,8},中序{4,7,2,1 ...

  5. C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解

    剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...

  6. 剑指Offer - 九度1385 - 重建二叉树

    剑指Offer - 九度1385 - 重建二叉树2013-11-23 23:53 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的 ...

  7. 剑指offer_面试题6_重建二叉树(分解步骤,逐个击破)

    题目:输入某二叉树的前序遍历和中序遍历的结果.请重建出该二叉树.如果输入的前序遍历和中序遍历的结果中都不含反复的数字. 比如:输入前序遍历 {1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7 ...

  8. 剑指offer——面试题8:二叉树的下一个节点

    // 面试题8:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. ...

  9. 剑指offer(4)重建二叉树

    题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...

随机推荐

  1. 运维干货|交换机不同VLAN之间及相同VLAN之内进行隔离

    文中所展示的内容为VLAN与VLAN之间分隔关系,如相同VLAN用户之间进行分隔,相同VLAN一组用户之间允许通信并与其它一组用户之间进行分隔,属于VLAN的高级应用范畴.本文来源于智象运维某大神的日 ...

  2. 爬虫入门到放弃系列07:js混淆、eval加密、字体加密三大反爬技术

    前言 如果再说IP请求次数检测.验证码这种最常见的反爬虫技术,可能大家听得耳朵都出茧子了.当然,也有的同学写了了几天的爬虫,觉得爬虫太简单.没有啥挑战性.所以特地找了三个有一定难度的网站,希望可以有兴 ...

  3. windows平台 cloin +rust 开发环境搭建

    rust 安装请看上一篇 clion 下载地址 破解 教程 1.先执行reset_jetbrains_eval_windows.vbs 2.打开软件选择免费使用 将ide-eval-resetter- ...

  4. PAT (Advanced Level) Practice 1011 World Cup Betting (20 分) 凌宸1642

    PAT (Advanced Level) Practice 1011 World Cup Betting (20 分) 凌宸1642 题目描述: With the 2010 FIFA World Cu ...

  5. 北航OO第一单元作业总结(Retake)

    前言:当我写这篇博客的时候,我的心情是复杂的,因为这实际上是我第二次写这篇博客--我今年重修的这门课.我对去年的成绩心有不甘--在激烈的竞争下,我虽然尽可能完成了所有作业(仅一次作业未通过弱测),但爆 ...

  6. 报错:Method definition shorthands are not supported by current JavaScript version

    当你在html中使用调用js中的方法时,会出现这行报错: method definition shorthands are not supported by current JavaScript ve ...

  7. 浅谈 C# Assembly 与 IL (一):C# Assembly 与 Reflection

    作者:Compasslg 前言 前一阵子想利用闲余时间写一个 Unity 游戏的翻译工具,主要是用于翻译一些内嵌在代码中的文本,最初想偷懒看了一下网上的教学推荐说可以先利用DnSpy.ILSpy等工具 ...

  8. Socket 多任务(多进程/线程、I/O多路复用、事件驱动开发框架)

    0. 概述 1. 循环版实现多连接 2. threading.Thread 多线程 3. SockerServer 实现多任务 3.1 ForkingMixIn - 多进程(限 linux) 3.2 ...

  9. VScode 使用提示

    vscode 配置xdebug参考 vscode配置phpxdebug 未完,待续!

  10. 功能:Java8新特性steam流

    Java8新特性steam流 一.包装数据类型 @Test public void main22() { List<Integer> list = new ArrayList<Int ...