首页 > 其他分享 >【技术积累】数据结构中的二叉树【一】

【技术积累】数据结构中的二叉树【一】

时间:2023-06-10 15:24:34浏览次数:25  
标签:积累 左子 遍历 右子 二叉树 数据结构 root 节点

什么是二叉树

二叉树是一种树形数据结构,由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。在二叉树中,每个节点的左子节点小于该节点的值,在该节点的右侧的子节点大于该节点的值。

二叉树的特点是易于搜索、插入和删除操作。

  1. 在搜索时,从根节点开始,如果被查找值等于当前节点的值,则搜索结束。
  2. 如果当前节点的值大于被查找值,则继续搜索左子节点;
  3. 如果当前节点的值小于被查找值,则继续搜索右子节点。
  4. 插入和删除节点的操作也类似。

二叉树可分为满二叉树、完全二叉树、平衡二叉树、二叉搜索树等多种类型,不同类型的二叉树有不同的特点和应用场景。

  1. 满二叉树是每个节点都有两个子节点的二叉树
  2. 完全二叉树则是除了最后一层节点之外,每一层节点都是满的,最后一层节点从左往右排列。
  3. 平衡二叉树是指左右子树高度差不超过1的二叉树。
  4. 二叉搜索树是按照特定规则构建的二叉树,每个节点的左子节点小于该节点的值,在该节点的右侧的子节点大于该节点的值。

二叉树在计算机科学领域中有广泛的应用,例如在搜索算法、编译器、数据库、操作系统等领域。

二叉树的高度,深度,宽度,平衡是什么

1. 二叉树的高度:

二叉树的高度是指从根节点到最深节点的距离,即根节点到最远叶子节点的最短路径。一般使用递归算法来计算二叉树的高度,即树的高度等于左子树高度和右子树高度中的较大值加一。

例如,对于下图所示的二叉树,其高度为4:

                    A
                   /  \
                  B    C
                 / \    \
                D   E    F
                           \
                            G

 

2. 二叉树的深度:

二叉树的深度是指从根节点到某个节点的距离,即从根节点到该节点的路径上经过的节点数。如果该节点是根节点,则深度为0,否则深度等于其父节点的深度加一。

例如,对于上图中的节点B,其深度为1,节点G的深度为3。

 

3.二叉树的宽度:

二叉树的宽度指的是二叉树某一层中最多节点的个数。为了计算树的宽度,需要使用BFS(广度优先搜索)算法,从根节点开始逐层遍历二叉树,记录每一层中节点的个数(即该层宽度),然后取所有层宽度的最大值即可。

例如,对于下面这棵二叉树:

        A
      /   \
     B     C
   /  \      \
  D    E      F

如果从根节点开始遍历二叉树,每一层中节点的个数为:

* 第1层:1个节点
* 第2层:2个节点
* 第3层:3个节点

因此,这棵二叉树的宽度是3。

需要注意的是,如果二叉树的某一层节点数目很少,那么这一层的宽度可能会影响树的整体宽度。在实际应用中,通常会根据具体场景选择不同的度量标准,如节点数、边数、占用的存储空间等。

 

4. 平衡二叉树:

平衡二叉树是指一棵二叉树,其中任意节点的左右子树的深度差不超过1。在平衡二叉树中,所有节点的左右子树深度差别不大,能够保证树在查询、插入和删除操作时,均能保持较高的性能表现。

例如,下图所示的二叉树就是一棵平衡二叉树:

               A
            /    \
           B      C
          / \    / \
         D   E  F   G

左右子树的深度差不超过1,左子树深度为2,右子树深度为2,因此它是一棵平衡二叉树。

 

二叉树的节点数和高度与叶子节点数的关系是什么?

二叉树的节点数与高度的关系可以表示为:如果二叉树的高度为h,则节点总数为2^(h+1) - 1

叶子节点数与高度的关系可以表示为:如果二叉树的高度为h,则叶子节点总数最多为2^h,最少为2^(h-1)。

因此,叶子节点数的范围是 [2^(h-1), 2^h],并且二叉树的叶子节点数和节点总数之间的关系是近似线性的。

 

二叉树前序遍历

1. 概念

前序遍历是二叉树遍历的一种方法,也叫做先根遍历。在前序遍历中,首先访问根节点,然后依次遍历其左子树和右子树。具体来说,在前序遍历中,每个节点的访问顺序为:根节点 → 左子树 → 右子树。

2. 步骤

前序遍历的步骤如下:

(1) 访问二叉树的根节点。

(2) 递归遍历左子树,直到左子树为空。

(3) 递归遍历右子树,直到右子树为空。

3. 伪代码

前序遍历的伪代码如下:

function preorderTraversal(root) {
    if (root == null) {
        return;
    }
    visit(root); // 访问根节点
    preorderTraversal(root.left); // 遍历左子树
    preorderTraversal(root.right); // 遍历右子树
}

二叉树中序遍历

1. 概念

中序遍历是二叉树遍历的一种方法。在中序遍历中,二叉树的节点按照以下顺序依次遍历:左子树 → 根节点 → 右子树。

2. 步骤

中序遍历的步骤如下:

(1) 递归遍历左子树,直到左子树为空。

(2) 访问二叉树的根节点。

(3) 递归遍历右子树,直到右子树为空。

3. 伪代码

中序遍历的伪代码如下:

function inorderTraversal(root) {
    if (root == null) {
        return;
    }
    inorderTraversal(root.left); // 遍历左子树
    visit(root); // 访问根节点
    inorderTraversal(root.right); // 遍历右子树
}

二叉树后续遍历

1. 概念

后序遍历是二叉树遍历的一种方法。在后序遍历中,二叉树的节点按照以下顺序依次遍历:左子树 → 右子树 → 根节点。

2. 步骤

后序遍历的步骤如下:

(1) 递归遍历左子树,直到左子树为空。

(2) 递归遍历右子树,直到右子树为空。

(3) 访问二叉树的根节点。

3. 伪代码

后序遍历的伪代码如下:

function postorderTraversal(root) {
    if (root == null) {
        return;
    }
    postorderTraversal(root.left); // 遍历左子树
    postorderTraversal(root.right); // 遍历右子树
    visit(root); // 访问根节点
}

二叉树查找操作复杂度

二叉搜索树中查找某个元素的步骤如下:

1. 从二叉搜索树的根节点开始遍历。

2. 如果当前节点为空,则返回null;如果当前节点的值等于目标值,则返回当前节点。

3. 如果当前节点的值大于目标值,则以当前节点的左子树为目标继续查找;如果当前节点的值小于目标值,则以当前节点的右子树为目标继续查找。

4. 重复执行第2和第3步,直到找到目标节点或者遍历至叶子节点为止。

伪代码如下所示:

function search(root, target):
    if (root == null) return null // 如果根节点为空,则直接返回null
    if (root.value == target) return root // 如果根节点的值等于目标值,则返回根节点
    
    if (root.value > target) // 如果根节点的值大于目标值,则在左子树中查找
        return search(root.left, target)
    else // 如果根节点的值小于目标值,则在右子树中查找
        return search(root.right, target)

二叉搜索树中查找某个元素的时间复杂度是O(log N),其中N为二叉搜索树中节点的数量。这是因为每次查找都会将搜索区域缩小一半,因此查找的次数最多是二叉树深度的两倍,而二叉树深度是log N级别的。

二叉树插入操作

1. 概念

二叉搜索树是一种特殊的二叉树,它满足以下性质:对于每个节点,它的左子树的所有节点的值小于该节点的值,它的右子树的所有节点的值大于该节点的值。

插入操作是指向二叉搜索树中添加新节点的过程,使得二叉搜索树仍然保持其有序性。

2. 步骤

二叉搜索树的插入操作步骤如下:

(1) 从根节点开始查找,比较当前节点的值和待插入节点的值。

(2) 如果当前节点为空,则将待插入节点插入到该位置,完成插入操作。

(3) 如果待插入节点的值小于当前节点的值,则在左子树中继续查找。

(4) 如果待插入节点的值大于当前节点的值,则在右子树中继续查找。

(5) 对查找到的节点重复上面的操作,直到找到合适的位置将待插入节点插入到树中。

3. 伪代码

二叉搜索树的插入操作的伪代码如下:

function insert(root, val) {
    if (root == null) {
        root = new TreeNode(val);
        return root;
    }
    if (val < root.val) {
        root.left = insert(root.left, val);
    } else if (val > root.val) {
        root.right = insert(root.right, val);
    }
    return root;
}

二叉树的删除操作

1. 概念

二叉搜索树的删除操作是指从二叉搜索树中删除一个节点的过程,同时保证删除后的二叉搜索树仍然满足其有序性质。

2. 步骤

二叉搜索树的删除操作步骤如下:

(1) 如果待删除节点为叶子节点,则直接删除该节点。

(2) 如果待删除节点只有一个子节点,则将该子节点替换到待删除节点的位置。

(3) 如果待删除节点有两个子节点,则先找到右子树的最小值节点,使用该节点替换待删除节点,并递归删除右子树中的最小值节点。

3. 伪代码

二叉搜索树的删除操作的伪代码如下:

function deleteNode(root, key) {
    if (root === null) {
        return null;
    } else if (key < root.val) {
        root.left = deleteNode(root.left, key);
    } else if (key > root.val) {
        root.right = deleteNode(root.right, key);
    } else {
        if (root.left === null && root.right === null) {
            root = null;
        } else if (root.left === null) {
            root = root.right;
        } else if (root.right === null) {
            root = root.left;
        } else {
            let minNode = findMin(root.right);
            root.val = minNode.val;
            root.right = deleteNode(root.right, minNode.val);
        }
    }
    return root;
}

function findMin(node) {
    while (node.left !== null) {
        node = node.left;
    }
    return node;
}

二叉树的遍历可以用来做什么

1. 二叉树的中序遍历可以用来做什么?

二叉树的中序遍历方法是先访问左子树,再访问根节点,最后访问右子树;因此,中序遍历可以帮助我们实现以下操作:

(1)从小到大遍历二叉搜索树:因为按照中序遍历的顺序,所有节点的值都会按从小到大的顺序输出,所以可以用中序遍历将二叉搜索树中的节点从小到大遍历。

(2)创建二叉搜索树:可以通过将节点按照中序遍历的顺序依次插入二叉搜索树来创建一颗新的二叉搜索树。

(3)查找二叉搜索树中的节点:通过进行中序遍历,可以找到指定值的节点。

2. 二叉树的后序遍历可以用来做什么?

二叉树的后序遍历方法是先访问左子树,再访问右子树,最后访问根节点;因此,后序遍历可以帮助我们实现以下操作:

(1)计算二叉树表达式:可以通过后序遍历以及栈的数据结构来计算二叉树表达式。

(2)释放二叉树节点:通过后序遍历的方式释放二叉树的每一个节点。

(3)构建二叉树的镜像:通过后序遍历的方式,可以先构建出原二叉树的镜像的右子树,再构建出镜像的左子树,最后创建根节点,获得二叉树的镜像树。

3. 二叉树的前序遍历可以用来做什么?

二叉树的前序遍历方法是先访问根节点,再访问左子树,最后访问右子树;因此,前序遍历可以帮助我们实现以下操作:

(1)序列化二叉树:可以按照前序遍历的顺序将二叉树转换为字符串,从而进行序列化操作。

(2)还原二叉树:通过前序遍历和中序遍历的结果,可以还原出原二叉树的结构。

(3)构建二叉搜索树:可以通过前序遍历的顺序依次插入节点来构建二叉搜索树。

标签:积累,左子,遍历,右子,二叉树,数据结构,root,节点
From: https://www.cnblogs.com/yyyyfly1/p/17471311.html

相关文章

  • redis通用命令及其五种基本数据结构
    Redis通用命令介绍:KEYS:查看符合模版的所有key,DEL:删除一个指定的KEYEXISTS:判断KEY是否存在EXPIRE:给一个key设置有效期,有效期到期时该KEY会自动删除TTL:查看一个key到剩余有效期示例:127.0.0.1:6379>existstest_key(integer)1127.0.0.1:6379>expire......
  • 二叉树的相关操作
    一.二叉树本文的数据结构基于C语言练习。C语言中的二叉树是一种数据结构,用于表示具有层次关系的数据集合。它由一个根节点开始,每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树有许多相关性质,其中一些重要的包括:深度:指从根节点到某个节点的路径长度。树的深度等于所有......
  • 二叉树
    给定二叉树结点的前序序列和中序序列,可以唯一确定该二叉树。因为前序序列的第一个元素是根结点,该元素将二叉树中序序列分成两部分,左边(设l个元素)表示左子树,若左边无元素,则说明左子树为空;右边(设r个元素)是右子树,若为空,则右子树为空。根据前序遍历中“根—左子树—右子树”......
  • 二叉树先序遍历算法的步骤
    //创建二叉树类型的结构体 //创建显得树节点并赋值并将该节点的左子树指针域和右子树指针域分别赋为NULL; //创建一个函数用于遍历二叉树并打印节点的值 //主函数将并将指针分别指向新的树节点  //执行遍历打印二叉树的节点的值 ......
  • 平衡二叉树
     1、平衡二叉树(AVL):它或者是一颗空树,左子树和右子树的深度之差不超过,且他的左子树和右子树都是一颗平衡二叉树2、平衡二叉树出现的原因:平衡二叉树就是在二叉排序树(BST)引入的,就是为了解决二叉排序树的不平衡性导致时间复杂度大大下降,AVL就保持住了BST的最好时间复杂度O(logn),所以每......
  • 初级数据结构--二叉树
    二叉树节点:树中的元素终端节点:分支数为0的节点有序树、无序树:节点左右排列顺序不得互换叫有序,反之为无序普通二叉树排序二叉树二叉顺序表定义和初始化typedefstructData{ intval;}Data;typedefstructTree{ Datadata; structTree*lbranch; structTree*rbranch;}T......
  • 代码随想录算法训练营第十七天|● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404
    110.平衡二叉树力扣题目链接(opensnewwindow)给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。示例1:给定二叉树[3,9,20,null,null,15,7]返回true。示例2:给定二叉树[1,2,2,3,3,nu......
  • 数据结构整理
    数据结构模板整理,请自取。线段树\(\operatorname{Sgt}\)\(\operatorname{BIT}\)平衡树\(\operatorname{Treap}\)\(\operatorname{Splay}\)\(\operatorname{FHQ-Treap}\)......
  • 【技术积累】算法中的动态规划【二】
    动态规划的优缺点是什么? 动态规划的优点是:可以解决一些复杂的问题,例如背包问题、最长公共子序列问题等;可以通过记忆化搜索来避免重复计算,提高效率;可以通过状态转移方程来简化问题,使问题更易于理解和解决;可以处理连续的问题,例如最大子段和问题。动态规划的缺点是:对于某......
  • 【技术积累】算法中的贪心算法【二】
    如何证明一个问题可以使用贪心算法解决?判断一个问题是否可以使用贪心算法解决,通常需要满足两个条件:贪心选择性质:问题的最优解可以通过一系列局部最优解得到。也就是说,在每一步选择中,都选择当前最优解,而不考虑之后的影响。最优子结构性质:问题的子问题的最优解可以推导出原问题......