[刷题] 剑指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, ...
随机推荐
- kong更改日志格式
基于业务的需求,需要对网关层的日志进行适当定制,以满足使用kibana的制图. 对于kong的日志格式更改,可查看到的资料都过于繁琐,特此记录. 修改kong的日志格式 # ctl edit depl ...
- Python信息搜集
1.IP查询 IP查询是通过当前所获取到的URL去查询对应IP地址的过程.可以应用socket库函数中的gethostbuname()获取域名所对应的IP值,代码如下: 查询域名www.biadu.c ...
- OO第三单元作业——魔教规格
OO第三单元作业--魔教规格 JML的理论基础和相关工具 JML(Java Modeling Language,Java建模语言),在Java代码种增加了一些符号,这些符号用来标志一个方法是干什么 ...
- 奇异值分解(SVD)与主成分分析(PCA)
本文中的内容来自我的笔记.撰写过程中,参考了书籍<统计学习方法(第2版)>和一些网络资料. 第一部分复习一些前置知识,第二部分介绍奇异值分解(SVD),第三部分介绍主成分分析(PCA).以 ...
- Vue3+Vite引入Echarts5.0图表库
1 概述 环境Vue3+Vite,需要引入ECharts库. 2 尝试 目前ECharts已更新到5.0版本,在Vue中引入并不难,npm/cnpm安装后在需要的组件中引入: import echar ...
- (十)Docker-V 详解
1. 作用 挂载宿主机的一个目录. 2. 案例 譬如我要启动一个centos容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定: # docker run -it -v /te ...
- 数栈运维实例:Oracle数据库运维场景下,智能运维如何落地生根?
从马车到汽车是为了提升运输效率,而随着时代的发展,如今我们又希望用自动驾驶把驾驶员从开车这项体力劳动中解放出来,增加运行效率,同时也可减少交通事故发生率,这也是企业对于智能运维的诉求. 从人工运维到自 ...
- Mysql下可能存在注入的点。
总结下mysql下可能存在注入的点,适用于mssql和oracle,先写语句,以后再写语句可能出现在哪些场景下: 针对查询: select * from x where id=* select * f ...
- Python语言程序设计(笔记)
1.平方根的格式化 知识点:平方根计算 pow(a,0.5)[可以计算负数,结果为复数] a**b 例题: 获得用户输入的一个整数a,计算a的平方根,保留小数点后3位,并打印输出. ...
- sublimeText常用插件
扩展包: EmmetAlignmentDocBlockrSideBarEnhancementsFileDiffsColorsublimelocalizationAutoFileNameA File ...