从0开始回顾数据结构---二叉树

简介: 二叉树1、二叉树的建立层序遍历重建二叉树测试样例:113 9 20 -1 -1 15 7 -1 -1 -1 -1中序遍历结果:9 3 15 20 7 #include<iostream> #include<cstdio>using namespace std;int n, num;//定义一棵二叉树 struct TreeNode{ int val; TreeNode* left; TreeNode* right; TreeNode(int _val) : val(_val), left(nullptr), right(nullp

二叉树

1、二叉树的建立

层序遍历重建二叉树

测试样例:

11

3 9 20 -1 -1 15 7 -1 -1 -1 -1

中序遍历结果:

9 3 15 20 7

#include<iostream> 
#include<cstdio>
using namespace std;
int n, num;
//定义一棵二叉树 
struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right; 
    TreeNode(int _val) : val(_val), left(nullptr), right(nullptr) {}
};
//层序遍历创建二叉树 
TreeNode* make(int p[], int u)
{ 
    if (u > n || p[u] == -1) return nullptr;
    TreeNode* root = new TreeNode(p[u]);
    root->left = make(p, u * 2);
    root->right = make(p, u * 2 + 1);
    return root;
}
//中序遍历二叉树 
void dfs(TreeNode* root)
{
    if (!root) return;
    dfs(root->left);
    cout << root->val << ' ';
    dfs(root->right);
}
int main()
{
  cin>>n;
  int p[n + 1];
  for(int i = 1; i <= n; i++) cin>>p[i];
  TreeNode* root = make(p, 1);
  dfs(root); 
  return 0;
}

2、前序遍历二叉树

样例:

递归写法

class Solution {
public:
    vector<int> res;
    vector<int> preorderTraversal(TreeNode* root) {
        if(!root) return {};
        dfs(root);
        return res;
    }
    void dfs(TreeNode* root){
        if(!root) return;
        res.push_back(root->val);
        dfs(root->left);
        dfs(root->right);
    }
};

迭代写法

迭代算法的本质是模拟递归,只不过递归使用了系统栈,而在迭代算法中我们使用stack模拟系统栈
迭代算法中,对于二叉树中的当前节点:

  1. 将当前节点压入栈中,并记录到答案中。
  2. 如果当前节点还有左儿子的话,继续将其左儿子压入栈中。
  3. 重复上述过程,直到最后一个节点没有左儿子为止。

这样,我们就将当前节点和它的左侧子节点全部访问完毕了(相当于我们已经访问了根节点和左子树节点),栈中存放着当前节点和它的全部左侧子节点。接下来我们该要去访问当前节点的右子树了,由于栈是先进后出的,此时栈顶元素的右子节点就是前序遍历的下一个要遍历的节点,因此:

  1. 取出栈顶元素的右子节点。
  2. 当前栈顶元素已经访问完毕,我们将其弹出。
  3. 如果当前栈顶元素的右子节点不为空,我们继续将其当成当前节点,重复对当前节点的处理过程。
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> stk;
        while(root || stk.size()){
            while(root){
                res.push_back(root->val);
                stk.push(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            root = root->right;
        }
        return res;
    }
};

完整代码

#include<iostream> 
#include<cstdio>
#include<stack>
using namespace std;
int n, num;
//定义一棵二叉树 
struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right; 
    TreeNode(int _val) : val(_val), left(nullptr), right(nullptr) {}
};
//层序遍历创建二叉树 
TreeNode* make(int p[], int u)
{
    if (u > n || p[u] == -1) return nullptr;
    TreeNode* root = new TreeNode(p[u]);
    root->left = make(p, u * 2);
    root->right = make(p, u * 2 + 1);
    return root;1
}
//迭代前序遍历二叉树 
void dfs(TreeNode* root)
{
  stack<TreeNode*> stk;
    while(root || stk.size()){
        while(root){
            cout<<root->val<<' ';
            stk.push(root);
            root = root->left;
        }
        root = stk.top();
        stk.pop();
        root = root->right;
    }
}
int main()
{
  cin>>n;
  int p[n + 1];
  for(int i = 1; i <= n; i++) cin>>p[i];
  TreeNode* root = make(p, 1);
  dfs(root); 
  return 0;
}

3、中序遍历二叉树

递归写法

class Solution {
public:
    vector<int> res;
    vector<int> inorderTraversal(TreeNode* root) {
        dfs(root);
        return res;
    }
    void dfs(TreeNode * root)
    {
        if(!root) return ;
        dfs(root->left); //左
        res.push_back(root->val); //根
        dfs(root->right); //右
    }
};

迭代写法

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> stk;
        while(root || stk.size()){
            while(root){
                stk.push(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            res.push_back(root->val);
            root = root->right;
        }
        return res;
    }
};

完整代码

#include<iostream> 
#include<cstdio>
#include<stack>
using namespace std;
int n, num;
//定义一棵二叉树 
struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right; 
    TreeNode(int _val) : val(_val), left(nullptr), right(nullptr) {}
};
//层序遍历创建二叉树 
TreeNode* make(int p[], int u)
{
    if (u > n || p[u] == -1) return nullptr;
    TreeNode* root = new TreeNode(p[u]);
    root->left = make(p, u * 2);
    root->right = make(p, u * 2 + 1);
    return root;
}
//迭代中序遍历二叉树 
void dfs(TreeNode* root)
{
  stack<TreeNode*> stk;
    while(root || stk.size()){
        while(root){
            stk.push(root);
            root = root->left;
        }
        root = stk.top();
        stk.pop();
        cout<<root->val<<' '; 
        root = root->right;
  }
}
int main()
{
  cin>>n;
  int p[n + 1];
  for(int i = 1; i <= n; i++) cin>>p[i];
  TreeNode* root = make(p, 1);
  dfs(root); 
  return 0;
}

4、后序遍历二叉树

递归写法

class Solution {
public:
    vector<int>res;
    vector<int> postorderTraversal(TreeNode* root) {
        dfs(root);
        return res;
    }
    void dfs(TreeNode* root)
    {
        if(root == NULL) return;
        dfs(root->left);
        dfs(root->right);
        res.push_back(root->val);
    }
};

迭代写法

  1. 前序遍历的顺序:根,左,右
  2. 可以根据类型前序遍历的思想,遍历出:根,右,左
  3. 再通过 2 中遍历出来的顺序,通过反转得到后序遍历:左,右,根
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> stk;
        while(root || stk.size()){
            while(root){
                res.push_back(root->val);
                stk.push(root);
                root = root->right;
            }
            root = stk.top();
            stk.pop();
            root = root->left;
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

完整代码

#include<iostream> 
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
int n, num;
//定义一棵二叉树 
struct TreeNode
{
    int val;
    TreeNode* left;
    TreeNode* right; 
    TreeNode(int _val) : val(_val), left(nullptr), right(nullptr) {}
};
//层序遍历创建二叉树 
TreeNode* make(int p[], int u)
{
    if (u > n || p[u] == -1) return nullptr;
    TreeNode* root = new TreeNode(p[u]);
    root->left = make(p, u * 2);
    root->right = make(p, u * 2 + 1);
    return root;
}
//迭代后序遍历二叉树 
void dfs(TreeNode* root)
{
  vector<int> res; 
  stack<TreeNode*> stk;
    while(root || stk.size()){
        while(root){
            res.push_back(root->val);
            stk.push(root);
            root = root->right;
        }
        root = stk.top();
        stk.pop();
        root = root->left;
    }
    reverse(res.begin(), res.end());
    for(int i = 0; i < res.size(); i++) cout<<res[i]<<' ';
}
int main()
{
  cin>>n;
  int p[n + 1];
  for(int i = 1; i <= n; i++) cin>>p[i];
  TreeNode* root = make(p, 1);
  dfs(root); 
  return 0;
}

5、什么是完全二叉树?

定义:若设二叉树的深度为k,除第k层外,其他各层(1~(k-1)层)的节点数都达到最大值,且第k层所有的节点都连续集中在最左边,这样的树就是完全二叉树。

性质:

  1. 对于任意一个节点,如果其有左子节点,那么它一定有右子节点。
  2. 对于任意一个节点,如果其有右子节点,那么它一定有左子节点。
  3. 最后一层的节点数目小于等于上一层的节点数目的两倍。
  4. 深度为k的完全二叉树至多有2^k-1个节点。

6、什么是二叉搜索树?

二叉搜索树又称二叉排序树,具有以下性质:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值;
  • 它的左右子树也分别为二叉搜索树。

注意:二叉搜索树中序遍历的结果是有序的。

7、什么是平衡二叉树?

定义:平衡二叉树是一种特殊的二叉树,其中每一个节点的左子树和右子树的高度差都不超过1。平衡二叉树的这种性质使得它在查找、插入和删除操作时具有较高的效率,并且能够保证操作的时间复杂度为O(logn)。

性质:

  1. 每个节点的左子树和右子树的高度差不超过1。
  2. 在插入或删除节点后,树会自动调整其结构以保持平衡。
  3. 在查找、插入和删除操作时,时间复杂度都是O(logn)。
  4. 平衡二叉树的高度较低,通常比普通的二叉搜索树要小。
相关文章
|
21天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
72 8
|
1月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
24 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
1月前
|
存储 算法 搜索推荐
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
26 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
1月前
|
Java
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
28 1
|
1月前
|
算法 Java C语言
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(一)
25 1
|
1月前
|
存储
【数据结构】二叉树链式结构——感受递归的暴力美学
【数据结构】二叉树链式结构——感受递归的暴力美学
|
1月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
1月前
|
存储 算法 调度
数据结构--二叉树的顺序实现(堆实现)
数据结构--二叉树的顺序实现(堆实现)
|
1月前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(三)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
|
1月前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(二)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解