【数据结构与算法】第十章:树和二叉树

简介: 树结构是一类重要的非线性数据结构。树在计算机领域中也得到广泛应用,尤以二叉树最为常用。本章将重点介绍树的结构定义及二叉树的相关操作。

🙊🙊作者主页:🔗求不脱发的博客

📔📔 精选专栏:🔗数据结构与算法

📋📋 精彩摘要:树结构是一类重要的非线性数据结构。树在计算机领域中也得到广泛应用,尤以二叉树最为常用。本章将重点介绍树的结构定义及二叉树的相关操作。

💞💞觉得文章还不错的话欢迎大家点赞👍➕收藏⭐️➕评论💬支持博主🤞


📚目录

📖【数据结构与算法】第十章:树和二叉树

📝1️⃣树

📝2️⃣二叉树


📖【数据结构与算法】第十章:树和二叉树


📝1️⃣树

✨树的定义

树是n(n>=0)个结点的有限集,或为空树,或为非空树。

对于非空树T:

    1. 有且仅有一个称之为根的结点。
    2. 除根结点外,其余结点可分为m个互不相交的有限集T1,T2,...,Tm,其中每个集合本身又是一棵树,称为根结点的子树。

    image.gif编辑

    树的其他表示形式:

    image.gif编辑

    ✨树的基本术语

    image.gif编辑

      1. 结点:数中的一个独立单元。包含一个数据元素及指向其子树的分支。如上图中的A、B、C、D等。
      2. 结点的度:结点拥有的子树树称为结点的度。
      3. 树的度:结点拥有的子树树称为结点的度。
      4. 叶子:度为0的结点称为叶子或终端结点。结点K、L、F、G、M、I、J都是树的叶子。
      5. 森林:指m颗不想交的树的集合(例如删除A后的子树个数)。
      6. 有序树:结点各子树从左至右有序,不能互换(左为第一)。
      7. 无序树:结点各子树可互换位置。
      8. 非终端结点:度不为0的结点称为非终端结点或分支结点。除根结点之外,非终端结点也称为内部结点。
      9. 双亲和孩子:结点的子树的根称为该结点的孩子,相应地,该结点称为孩子的双亲。例如,B的双亲为A,B的孩子有E和F。
      10. 兄弟:同一个双亲的孩子之间互称兄弟。例如,H、I和J互为兄弟。
      11. 祖先:从根到该结点所经分支上的所有结点。例如,M的祖先为A、D和H。
      12. 子孙:以某结点为根的子树中的任一结点都称为该结点的子孙。如B的子孙为E、K、L和F。
      13. 层次:结点的层次从根开始定义起,根为第一层,根的孩子为第二层。树中任一结点的层次等千其双亲结点的层次加l。
      14. 堂兄弟:双亲在同一层的结点互为堂兄弟。例如,结点G与E、F、H、I、J互为堂兄弟。

      ✨树的抽象数据类型定义

      根据树的结构定义,加上树的一组基本操作就构成了树的抽象数据类型定义:

      ADT Tree{ 
          数据对象D:D是具有相同特性的数据元素的集合。
          数据关系R:若D为空集,则称为空树;
      } ADT Tree;

      image.gif

      基本操作:

             InitTree(&T)

                 操作结果:构造空树T。

             DestroyTree (&T)

                 初始条件:树T存在。

                 操作结果:销毁树T。

             CreateTree(&T,definition)

                 初始条件:defini巨on给出树T的定义。

                 操作结果:按defini巨on构造树T。

             ClearTree(&T)

                 初始条件:树T存在。

                 操作结果:将树T清为空树。TreeEmpty(T)

             TreeEmpty(T)

                 初始条件:树T存在。

                 操作结果:若T为空树,则返回true,否则false。

             TreeDepth(T)

                 初始条件:树T存在。

                 操作结果:返回T的深度。

             Root(T)

                 初始条件:树T存在。

                 操作结果:返回T的根。

             Value(T,cur_e)

                 初始条件:树T存在,cur_e是T中某个结点。

                 操作结果:返回cur_e的值。

             Assign(T,cur_e,value)

                 初始条件:树T存在,cur_e是T中某个结点。

                 操作结果:结点cur_e赋值为value。

             Parent(T,cur_e);

                 初始条件:树T存在,cur_e是T中某个结点。

                 操作结果:若cur_e是T的非根结点,则返回它的双亲,否则函数值为“空”。

             LeftChild(T,cur_e)

                 初始条件:树T存在,cur_e是T中某个结点。

                 操作结果:若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回“空”。

             RightSibling(T,cur_e)

                 初始条件:树T存在,cur_e是T中某个结点。

                 操作结果:若cur_e有右兄弟,则返回它的右兄弟,否则函数值为“空”。

             InsertChild(&T,p,i,c)

                 初始条件:树T存在,p指向T中某个结点,1,;;i所指结点的度+1, 非空树c与T不相交。

                 操作结果:插入c为T中p指结点的第l.棵子树

             DeleteChild(&T,p,i)

                 初始条件:树T存在,p指向T中某个结点,1,;;i指结点的度。

                 操作结果:删除T中p所指结点的第l.棵子树

             TraverseTree(T)

                 初始条件:树T存在。

                 操作结果:按某种次序对T的每个结点访问一次。

      📝2️⃣二叉树

      ✨二叉树的定义

      二叉树树是n(n>=0)个结点的有限集,或为空树,或为非空树。

      基本特点:

        1. 结点的度小于等于2。
        2. 有序树(子树有序,不能颠倒)。

        对于非空二叉树T:

          1. 有且仅有一个称之为根的结点;
          2. 除根结点以外的其余结点分为两个互不相交的子集T1和T2,分别称为T的左子树和右子树,且T1和T2本身又都是二叉树。

          二叉树与树一样具有递归性质,二叉树与树的区别主要有以下两点:

            1. 二叉树每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点);
            2. 二叉树的子树有左右之分,其次序不能任意颠倒。

            image.gif编辑

             ✨二叉树的抽象数据类型定义

            ADT BinaryTree{ 
                数据对象D:D是具有相同特性的数据元素的集合。
                数据关系R:
            } ADT BinaryTree;

            image.gif

            基本操作P:

                   InitBiTree(&T)

                       操作结果:构造空二叉树T。

                   DestroyBiTree(&T)

                       初始条件:二叉树T存在。

                       操作结果:销毁二叉树T。

                   Crea七eBiTree(&T,definition)

                       初始条件;definition给出二叉树T的定义。

                       操作结果:按definition构造二叉树T。

                   ClearBiTree(&T)

                       初始条件:二叉树T存在。

                       操作结果:将二叉树T清为空树。

                   BiTreeEmpty(T)

                       初始条件:二叉树T存在。

                       操作结果:若T为空二叉树,则返回true,否则false。

                   BiTreeDepth (T)

                       初始条件:二叉树T存在。

                       操作结果:返回T的深度。

                   Root(T)

                       初始条件:二叉树T存在。

                       操作结果:返回T的根。

                   Value(T,e)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:返回e的值。

                   Assign(T,&e,value)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:结点e赋值为value。

                   Parent(T,e)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:若e是T的非根结点,则返回它的双亲,否则返回“空”。

                   LeftChild(T,e)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:返回e的左孩子。若e无左孩子,则返回“空”。

                   RightChild(T,e)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:返回e的右孩子。若e无右孩子,则返回“空”。

                   LeftSibling (T, e)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回“空”。

                   RightSibling(T,e)

                       初始条件:二叉树T存在,e是T中某个结点。

                       操作结果:返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回“空”。

                   InsertChild(&T,p,LR,c)

                       初始条件:二叉树T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空。

                       操作结果:根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点的原有左或右子树成        为c的右子树。

                   DeleteChild (&T, p, LR)

                       初始条件:二叉树T存在,p指向T中某个结点,LR为0或1。

                       操作结果:根据LR为0或1,删除T中p所指结点的左或右子树。

                   PreOrderTraverse(T}

                       初始条件:二叉树T存在。

                       操作结果:先序遍历T,对每个结点访问一次。

                   InOrderTraverse(T)

                       初始条件:二叉树T存在。

                       操作结果:中序遍历T,对每个结点访问一次。

                   PostOrderTraverse(T}

                       初始条件:二叉树T存在。

                       操作结果:后序遍历T,对每个结点访问一次5

                   LevelOrderTraverse(T)

                       初始条件:二叉树T存在。

                       操作结果:层序遍历T,对每个结点访问一次。

             ✨二叉树的性质

              1. 在二叉树的第i层上最多有2^(i-1)个结点。
              2. 深度为k的二叉树至多有2^k-1个结点。
              3. 对于任何一颗二叉树,若2度的结点数1有n2个则叶子数n0必定为n2+1。(即 n0 = n2 + 1)
              4. 具有n个结点的完全二叉树的深度必为[log2n]+1。
              5. 对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2。

              对此有如下定义:

              image.gif编辑image.gif编辑

                                   (满二叉树 )                                        (完全二叉树)            

              满二叉树:一棵深度为k 且有2k -1个结点的二叉树。(特点:每层都“充满”了结点

              完全二叉树:深度为k 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k 的满二叉树中编号从1至n的结点一一对应

              满二叉树与完全二叉树的区别:

              满二叉树是叶子一个也不少的树,而完全二叉树虽然前n-1层是满的,但最底层却允许在右边缺少连续若干个结点。满二叉树是完全二叉树的一个特例。

              相关文章
              |
              14天前
              |
              存储 搜索推荐 算法
              【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
              本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
              57 16
              |
              7天前
              |
              算法
              分享一些提高二叉树遍历算法效率的代码示例
              这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
              |
              10天前
              |
              存储 缓存 算法
              如何提高二叉树遍历算法的效率?
              选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
              29 5
              |
              14天前
              |
              C语言
              【数据结构】二叉树(c语言)(附源码)
              本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
              63 8
              |
              10天前
              |
              算法
              树的遍历算法有哪些?
              不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
              19 2
              |
              13天前
              |
              机器学习/深度学习 JSON 算法
              二叉树遍历算法的应用场景有哪些?
              【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
              23 0
              |
              1月前
              |
              存储 算法 关系型数据库
              数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
              这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
              19 0
              数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
              |
              1月前
              |
              Java C++
              【数据结构】探索红黑树的奥秘:自平衡原理图解及与二叉查找树的比较
              本文深入解析红黑树的自平衡原理,介绍其五大原则,并通过图解和代码示例展示其内部机制。同时,对比红黑树与二叉查找树的性能差异,帮助读者更好地理解这两种数据结构的特点和应用场景。
              28 0
              |
              1月前
              |
              存储 算法
              探索数据结构:分支的世界之二叉树与堆
              探索数据结构:分支的世界之二叉树与堆
              |
              25天前
              |
              算法 安全 数据安全/隐私保护
              基于game-based算法的动态频谱访问matlab仿真
              本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。