构建二叉树
构建二叉树、线段树
本文图文并茂讲解从前序遍历、中序续遍历构建二叉树或者从后序遍历、中序续遍历又或者从前序遍历、后序续遍历构建二叉树的原理,比附上相关的习题。
注意:
将提供以下图文链接供大家理解:
图文链接:
飞书图解链接🎉🎉🎉
密码:86N2619&
1. 从前序遍历、中序续遍历构建二叉树
题目一
AC代码,展开查看
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int, int> pos;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0; i < inorder.size(); i ++ ) pos[inorder[i]] = i;
return build(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
}
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir){
if(pl > pr) return nullptr;
auto root = new TreeNode(preorder[pl]);
int k = pos[root -> val];
root -> left = build(preorder, inorder, pl + 1, k - il + pl, il, k - 1);
root -> right = build(preorder, inorder, k - il + pl + 1, pr, k + 1, ir);
return root;
}
};
2. 从后序遍历、中序续遍历构建二叉树
题目一
AC代码,展开查看
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int, int> pos;
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
for(int i = 0; i < inorder.size(); i ++ ) pos[inorder[i]] = i;
return build(inorder, postorder, 0, inorder.size() - 1, 0, postorder.size() - 1);
}
TreeNode* build(vector<int>& inorder, vector<int>& postorder, int il, int ir, int pl, int pr){
if(il > ir) return nullptr;
auto root = new TreeNode(postorder[pr]);
int k = pos[root -> val];
root -> left = build(inorder, postorder, il, k - 1, pl, pl + k - il - 1);
root -> right = build(inorder, postorder, k + 1, ir, pl + k - il, pr - 1);
return root;
}
};
题目二
前置知识
- 数组模拟二叉树
- 数组大小为: 将此二叉树转化为完全二叉树的节点的数目 + 1
- 注意: 节点必须从索引1开始
示例代码:
AC代码,展开查看
#include<bits/stdc++.h>
using namespace std;
const int N = 9;
int a[N]; // 根节点在a[1]
void proOrder(int index){
if(index > N) return;
cout << a[index] << endl;
proOrder(2 * index);
proOrder(2 * index + 1);
}
int main(){
for(int i = 1; i <= N; i ++ ) a[i] = i;
proOrder(1);
return 0;
}
/*
运行结果
1
2
4
8
9
5
3
6
7
*/
- 结构体二叉树
示例代码:
AC代码,展开查看
#include<bits/stdc++.h>
using namespace std;
const int N = 9;
struct Node{
int val;
Node* left;
Node* right;
Node(int val){
this -> val = val;
}
~Node(){
cout << "回收掉的val值为: " << this -> val << "\n";
}
};
Node* buildTree(int val){
if(val > N) return nullptr;
Node* root = new Node(val);
root -> left = buildTree(2 * val);
root -> right = buildTree(2 * val + 1);
return root;
}
void proOrder(Node* root){
if(!root) return;
cout << "前序: " << root -> val << "\n";
proOrder(root -> left);
proOrder(root -> right);
}
void inOrder(Node* root){
if(!root) return;
inOrder(root -> left);
cout << "中序: " << root -> val << "\n";
inOrder(root -> right);
}
void postOrder(Node* root){
if(!root) return;
postOrder(root -> left);
postOrder(root -> right);
delete root;
}
int main(){
auto root = buildTree(1);
proOrder(root);
inOrder(root);
postOrder(root);
return 0;
}
/*
运行结果
1
2
4
8
9
5
3
6
7
*/
解题思路:
- 根据后序遍历和中序遍历构建出二叉树,然后进行一次前序遍历
AC代码,展开查看
#include<bits/stdc++.h>
using namespace std;
const int N = 10; // 长度小于等于8
unordered_map<char, int> pos;
struct Node{
char val;
Node* left;
Node* right;
Node(int val){
this -> val = val;
}
~Node(){
cout << "回收掉的val值为: " << this -> val << "\n";
}
};
Node* build(string& inorder, string& postorder, int il, int ir, int pl, int pr);
Node* buildTree(string& inorder, string& postorder) {
for(int i = 0; i < inorder.size(); i ++ ) pos[inorder[i]] = i;
return build(inorder, postorder, 0, inorder.size() - 1, 0, postorder.size() - 1);
}
Node* build(string& inorder, string& postorder, int il, int ir, int pl, int pr){
if(il > ir) return nullptr;
auto root = new Node(postorder[pr]);
int k = pos[root -> val];
root -> left = build(inorder, postorder, il, k - 1, pl, pl + k - il - 1);
root -> right = build(inorder, postorder, k + 1, ir, pl + k - il, pr - 1);
return root;
}
void proOrder(Node* root){
if(!root) return;
cout << root -> val;
proOrder(root -> left);
proOrder(root -> right);
}
void postOrder(Node* root){
if(!root) return;
postOrder(root -> left);
postOrder(root -> right);
delete root;
}
int main(){
string inStr, postStr;
cin >> inStr >> postStr;
auto root = buildTree(inStr, postStr);
proOrder(root);
postOrder(root);
return 0;
}
- 根据后序遍历和中序遍历输出前序遍历
AC代码,展开查看
#include<bits/stdc++.h>
using namespace std;
const int N = 10;
// 中序 后序
char inStr[N], postStr[N];
unordered_map<char, int> pos;
void dfs(char inStr[], char postStr[], int il, int ir, int pl, int pr){
if(ir >= il){
char c = postStr[pr]; // 根节点, 按序输出根节点即为前序遍历
printf("%c", c);
int k = pos[c];
dfs(inStr, postStr, il, k - 1, pl, k - il - 1 + pl);
dfs(inStr, postStr, k + 1, ir, k - il + pl, pr - 1);
}
}
int main(){
scanf("%s%s", inStr, postStr);
int n = strlen(inStr);
for(int i = 0; i < n; i ++ ) pos[inStr[i]] = i;
dfs(inStr, postStr, 0, n - 1, 0, n - 1);
return 0;
}
3. 从前序遍历、后序续遍历构建二叉树
题目一
AC代码,展开查看
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int, int> pos;
TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
for(int i = 0; i < postorder.size(); i ++ ) pos[postorder[i]] = i;
return build(preorder, postorder, 0, preorder.size() - 1, 0, postorder.size() - 1);
}
// postorder -> afterorder
TreeNode* build(vector<int>& preorder, vector<int>& postorder, int pl, int pr, int al, int ar){
if(pl > pr) return nullptr;
auto root = new TreeNode(preorder[pl]);
if(pl == pr) return root;
int k = pos[preorder[pl + 1]];
root -> left = build(preorder, postorder, pl + 1, k - al + pl + 1, al, k);
root -> right = build(preorder, postorder, k - al + pl + 2, pr, k + 1, ar);
return root;
}
};
线段树
#include<bits/stdc++.h>
#define lc p << 1
#define rc p << 1 | 1
using namespace std;
const int N = 5e5 + 10;
struct Node{
int l, r, sum, add;
};
Node tree[N * 4];
int w[N];
void pushUp(const int p){
tree[p].sum = tree[lc].sum + tree[rc].sum;
}
void build(const int p, const int l, const int r){
tree[p] = {l, r, w[l], 0};
if(l == r) return;
int m = l + r >> 1;
build(lc, l, m), build(rc, m + 1, r);
pushUp(p);
}
void pushDown(const int p){
if(tree[p].add){
tree[lc].sum += tree[p].add * (tree[lc].r - tree[lc].l + 1);
tree[rc].sum += tree[p].add * (tree[rc].r - tree[rc].l + 1);
tree[lc].add += tree[p].add;
tree[rc].add += tree[p].add;
tree[p].add = 0;
}
}
void update(const int p, const int x, const int y, const int k){
if(x <= tree[p].l && y >= tree[p].r){
tree[p].sum += (tree[p].r - tree[p].l + 1) * k;
tree[p].add += k;
return;
}
int m = tree[p].l + tree[p].r >> 1;
pushDown(p);
if(x <= m) update(lc, x, y, k);
if(y > m) update(rc, x, y, k);
pushUp(p);
}
int query(const int p, const int x, const int y){
if(x <= tree[p].l && y >= tree[p].r) return tree[p].sum;
int m = tree[p].l + tree[p].r >> 1;
pushDown(p);
int sum = 0;
if(x <= m) sum += query(lc, x, y);
if(y > m) sum += query(rc, x, y);
return sum;
}
int main(){
int T, n, a, x, y;
scanf("%d%d", &n, &T);
for(int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
build(1, 1, n);
while(T -- ){
scanf("%d%d%d", &a, &x, &y);
if(a == 1){
update(1, x, x, y);
}else{
printf("%d\n", query(1, x, y));
}
}
return 0;
}
海纳百川,有容乃大!如果文章有什么不足之处,还请大神们评论区留言指出,我在此表达感谢🥰!若大家喜欢我的作品,欢迎点赞、收藏、打赏🎉🎉🎉!

构建二叉树
浙公网安备 33010602011771号