从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. 平衡二叉树的高度较低,通常比普通的二叉搜索树要小。
目录
打赏
0
0
0
0
9
分享
相关文章
|
4月前
|
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
105 10
 算法系列之数据结构-二叉树
|
6月前
|
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
156 12
|
6月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
145 10
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
212 3
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
234 4
|
8月前
|
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
550 8
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
97 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
156 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
9月前
|
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)
83 1
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问