[刷题] 剑指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:\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:重建二叉树的更多相关文章
- 剑指offer面试题6 重建二叉树(c)
- 剑指offer面试题6  重建二叉树(java)
		注:(1)java中树的构建 (2)构建子树时可以直接利用Arrays.copyOfRange(preorder, from, to),这个方法是左开右闭的 package com.xsf.SordF ... 
- [刷题] 剑指offer 面试题18:删除链表节点
		要求 给定单向链表的头指针和一个节点指针,在O(1)时间内删除该节点 常规思路:从头节点a开始顺序遍历,发现p指向要删除的节点i,然后把p的m_pNext指向i的下一个节点j,时间复杂度O(n) O( ... 
- 剑指Offer:面试题6——重建二叉树(java实现)
		问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不包含重复的数字. 例如: 输入:前序{1,2,4,7,3,5,6,8},中序{4,7,2,1 ... 
- C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解
		剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ... 
- 剑指Offer - 九度1385 - 重建二叉树
		剑指Offer - 九度1385 - 重建二叉树2013-11-23 23:53 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的 ... 
- 剑指offer_面试题6_重建二叉树(分解步骤,逐个击破)
		题目:输入某二叉树的前序遍历和中序遍历的结果.请重建出该二叉树.如果输入的前序遍历和中序遍历的结果中都不含反复的数字. 比如:输入前序遍历 {1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7 ... 
- 剑指offer——面试题8:二叉树的下一个节点
		// 面试题8:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. ... 
- 剑指offer(4)重建二叉树
		题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ... 
随机推荐
- 网关Ocelot功能演示安排的明明白白~~~
			前言 网关(Gateway)在微服务架构中至关重要,可以将其理解为是外部客户端(前端.MVC后台等调用方)与后台服务的连接点,通过这层可以做统一的处理,比如路由.身份认证和授权.服务治理等: 网关的好 ... 
- (原创)高DPI适配经验系列:(一)缩放比例与DPI对应关系
			一.前言 当下,2K分辨率已成为主流标配,3K.4K也已经广泛应用. 在屏幕尺寸不变的情况下,高分辨率也就意味着高DPI,对于桌面程序而言,除了先天就支持高DPI的框架外(如UWP.Electron等 ... 
- Istio安全-证书管理(实操一)
			Istio安全-证书管理 目录 Istio安全-证书管理 插入现有CA证书 插入现有证书和密钥 部署Istio 配置示例services 校验证书 卸载 Istio的DNS证书管理 DNS证书的提供和 ... 
- 配置Jupyter环境:安装+补全+美化+常用库
			1 Jupyter简介 Jupyter Notebook是一个交互式笔记本,支持运行40多种编程语言,本质是一个Web应用程序,便于创建和共享文学化程序文档,支持实时代码,数学方程,可视化和Markd ... 
- (十三)VMware Harbor 身份验证模式
			VMware Harbor 修改Harbor仓库admin用户 参考:https://blog.csdn.net/qq_40460909 https://blog.csdn.net/qq_404609 ... 
- SAMBA 文件共享服务
			samba 通过简单配置就能够实现Linux系统与Windows系统之间的文件共享工作,也可实现Linux与Linux之间的文件共享. 在配置samba前,有个小建议:虚拟机的ip地址最好配置成静态的 ... 
- IDEA 2021版新建Maven、TomCat工程
			目录 2021版IDEA中Maven.TomCat配置 1.基于Webapp创建一个Maven项目 1.1 新建项目模板 1.2 指定名称 1.3 指定信息 1.4 指定Maven地址 1.5 构建成 ... 
- 4-1 Postman脚本的应用
			前面我们讲解了在接口发送每个请求,得到响应.这是接口本身的问题.但是"请求前后"的动作,是怎么处理的?比如在发送一个请求前,需要获取当前的时间戳,或者对我们的变量进行参数化,设置变 ... 
- git 避免重复输入用户名密码问题解决
			"store" 模式会将凭证用明文的形式存放在磁盘中,并且永不过期. 这意味着除非你修改了你在 Git 服务器上的密码,否则你永远不需要再次输入你的凭证信息. 这种方式的缺点是你的 ... 
- kali 中的内置工具
			askDing Life is short,use python 博客园 | 首页 | 新随笔 | 新文章 | 联系 | 订阅 | 管理 随笔: 326 文章: 5 评论: 4 引用: 0 kali菜 ... 
