C/C++每日一练(20230427) 二叉树专场(5)

简介: C/C++每日一练(20230427) 二叉树专场(5)

1. 从中序与后序遍历序列构造二叉树


根据一棵树的中序遍历与后序遍历构造二叉树。


注意:

你可以假设树中没有重复的元素。


例如,给出

中序遍历 inorder = [9,3,15,20,7]

后序遍历 postorder = [9,15,7,20,3]


返回如下的二叉树:

   3

  / \

 9  20

   /  \

  15   7

出处:

https://edu.csdn.net/practice/26654112

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution
{
public:
    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder)
    {
        if (0 == inorder.size() || 0 == postorder.size())
        {
            return NULL;
        }
        return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
    }
    TreeNode *build(vector<int> &inorder, int i1, int i2, vector<int> &postorder, int p1, int p2)
    {
        TreeNode *root = new TreeNode(postorder[p2]);
        int i = i1;
        while (i <= i2 && postorder[p2] != inorder[i])
        {
            i++;
        }
        int left = i - i1;
        int right = i2 - i;
        if (left > 0)
        {
            root->left = build(inorder, i1, i - 1, postorder, p1, p1 + left - 1);
        }
        if (right > 0)
        {
            root->right = build(inorder, i + 1, i2, postorder, p1 + left, p2 - 1);
        }
        return root;
    }
};
vector<int> preorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> st;
    st.push(root);
    while (!st.empty()) {
        TreeNode* node = st.top();
        st.pop();
        if (node != nullptr) {
            res.push_back(node->val);
            st.push(node->right);
            st.push(node->left);
        }
    }
    return res;
}
string vectorToString(vector<int> vect) {
    stringstream ss;
  ss << "[";
    for (size_t i = 0; i < vect.size(); i++) {
      ss << vect[i] << (i < vect.size() - 1 ? "," : "");
    }
    ss << "]";
    return ss.str();
}
int main()
{
    Solution s;
    vector<int> inorder = {9,3,15,20,7};
    vector<int> postorder = {9,15,7,20,3};
    TreeNode* root = s.buildTree(inorder, postorder);
    vector<int> preorder = preorderTraversal(root);
    cout << vectorToString(preorder) << endl;
    return 0;
}


输出:

[3,9,20,15,7]


2. 从先序与中序遍历序列构造二叉树


根据一棵树的先序遍历与中序遍历构造二叉树。


注意:

你可以假设树中没有重复的元素。


例如,给出

先序遍历 preorder = [3,9,20,15,7]

中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

   3

  / \

 9  20

   /  \

  15   7

出处:

与上题类似,已知三种遍历中的两个且有中序,就能确定一棵二叉树。如果只有先序、后序,因为不能确定根的位置,所以无法确定。

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.empty() || inorder.empty()) {
            return nullptr;
        }
        unordered_map<int, int> pos;
        for (int i = 0; i < (int)inorder.size(); ++i) {
            pos[inorder[i]] = i;
        }
        return build(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1, pos);
    }
    TreeNode* build(vector<int>& preorder, int p1, int p2, vector<int>& inorder, int i1, int i2, unordered_map<int, int>& pos) {
        if (p1 > p2 || i1 > i2) {
            return nullptr;
        }
        int rootVal = preorder[p1];
        int i = pos[rootVal];
        TreeNode* root = new TreeNode(rootVal);
        root->left = build(preorder, p1 + 1, p1 + i - i1, inorder, i1, i - 1, pos);
        root->right = build(preorder, p1 + i - i1 + 1, p2, inorder, i + 1, i2, pos);
        return root;
    }
};
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> res;
    if (root == nullptr) {
        return res;
    }
    stack<TreeNode*> st1, st2;
    st1.push(root);
    while (!st1.empty()) {
        TreeNode* node = st1.top();
        st1.pop();
        st2.push(node);
        if (node->left != nullptr) {
            st1.push(node->left);
        }
        if (node->right != nullptr) {
            st1.push(node->right);
        }
    }
    while (!st2.empty()) {
        res.push_back(st2.top()->val);
        st2.pop();
    }
    return res;
}
string vectorToString(vector<int> vect) {
    stringstream ss;
  ss << "[";
    for (size_t i = 0; i < vect.size(); i++) {
      ss << vect[i] << (i < vect.size() - 1 ? "," : "");
    }
    ss << "]";
    return ss.str();
}
int main()
{
    Solution s;
    vector<int> preorder = {3,9,20,15,7};
    vector<int> inorder = {9,3,15,20,7};
    TreeNode* root = s.buildTree(preorder, inorder);
    vector<int> postorder = postorderTraversal(root);
    cout << vectorToString(postorder) << endl;
    return 0;
}


输出:

[9,15,7,20,3]


3. 二叉树展开为链表


给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

示例 1:


92075cab0821ae4b0edf18d3de9db0f1.jpeg


输入:root = [1,2,5,3,4,null,6]

输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []

输出:[]

示例 3:

输入:root = [0]

输出:[0]

提示:

   树中结点数在范围 [0, 2000] 内

   -100 <= Node.val <= 100

进阶:你可以使用原地算法(O(1) 额外空间)展开这棵树吗?

出处:

https://edu.csdn.net/practice/25405424

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution
{
public:
    void rconnect(TreeNode *&node, TreeNode *pmove)
    {
        if (pmove == nullptr)
            return;
        node->right = new TreeNode(pmove->val);
        node->left = nullptr;
        node = node->right;
        rconnect(node, pmove->left);
        rconnect(node, pmove->right);
    }
    void flatten(TreeNode *root)
    {
        if (root == nullptr)
            return;
        TreeNode *head = new TreeNode(null);
        TreeNode *newroot = head;
        rconnect(head, root);
        newroot = newroot->right->right;
        root->right = newroot;
        root->left = nullptr;
    }
};
TreeNode* buildTree(vector<int>& nums)
{
    if (nums.empty()) return nullptr;
  TreeNode *root = new TreeNode(nums.front());
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(!q.empty() && i < nums.size())
    {
        TreeNode *cur = q.front();
        q.pop();
        if(i < nums.size() && nums[i] != null)
        {
            cur->left = new TreeNode(nums[i]);
            q.push(cur->left);
        }
        i++;
        if(i < nums.size() && nums[i] != null)
        {
            cur->right = new TreeNode(nums[i]);
            q.push(cur->right);
        }
        i++;
    }
    return root;
}
vector<int> preorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> st;
    st.push(root);
    while (!st.empty()) {
        TreeNode* node = st.top();
        st.pop();
        if (node != nullptr) {
            res.push_back(node->val);
            st.push(node->right);
            st.push(node->left);
        }
        else
          res.push_back(null);
    }
    while (res.back()==null)
      res.pop_back();
    return res;
}
string vectorToString(vector<int> vect) {
    stringstream ss;
  ss << "[";
    for (size_t i = 0; i < vect.size(); i++)
  {
        ss << (vect[i] == null ? "null" : to_string(vect[i]));
        ss << (i < vect.size() - 1 ? "," : "]");
    }
    return ss.str();
}
int main() {
  Solution s;
    vector<int> nums = {1,2,5,3,4,null,6};  
    TreeNode* root = buildTree(nums);  
    s.flatten(root); 
    cout << vectorToString(preorderTraversal(root)) << endl;
    return 0;  
}





输出:

[1,null,2,null,3,null,4,null,5,null,6]








目录
相关文章
二叉树进阶面试题(精华总结)【C++版本】
二叉树进阶面试题(精华总结)【C++版本】
145 1
|
存储 编译器 数据库
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
415 0
|
算法 C++ 开发者
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
328 0
|
2月前
|
C++
基本二叉树与排序二叉树(C++源码)
本程序实现二叉树基本操作与二叉排序树应用。支持前序建树、四种遍历、求深度、叶子数、第K层节点数及查找功能;并实现二叉排序树的构建、中序输出与查找比较次数统计,分析不同插入顺序对树形态和查找效率的影响。
|
11月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
318 12
|
11月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
192 10
|
11月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
477 3
|
存储 C++
【C++】二叉树进阶之二叉搜索树(下)
【C++】二叉树进阶之二叉搜索树(下)
99 4
|
Java 编译器 C++
【C++】二叉树进阶之二叉搜索树(上)
【C++】二叉树进阶之二叉搜索树(上)
99 3
|
算法 C++
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
115 2