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

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

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

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

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

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


📚目录

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

📝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层是满的,但最底层却允许在右边缺少连续若干个结点。满二叉树是完全二叉树的一个特例。

              相关文章
              |
              2月前
              |
              算法
              数据结构之博弈树搜索(深度优先搜索)
              本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
              55 0
              |
              6天前
              |
              存储 算法 Python
              文件管理系统中基于 Python 语言的二叉树查找算法探秘
              在数字化时代,文件管理系统至关重要。本文探讨了二叉树查找算法在文件管理中的应用,并通过Python代码展示了其实现过程。二叉树是一种非线性数据结构,每个节点最多有两个子节点。通过文件名的字典序构建和查找二叉树,能高效地管理和检索文件。相较于顺序查找,二叉树查找每次比较可排除一半子树,极大提升了查找效率,尤其适用于海量文件管理。Python代码示例包括定义节点类、插入和查找函数,展示了如何快速定位目标文件。二叉树查找算法为文件管理系统的优化提供了有效途径。
              37 5
              |
              6天前
              |
              数据库
              数据结构中二叉树,哈希表,顺序表,链表的比较补充
              二叉搜索树,哈希表,顺序表,链表的特点的比较
              数据结构中二叉树,哈希表,顺序表,链表的比较补充
              |
              2月前
              |
              存储 缓存 算法
              在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
              在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
              59 5
              |
              2月前
              |
              机器学习/深度学习 存储 算法
              数据结构实验之二叉树实验基础
              本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
              89 4
              |
              2月前
              |
              存储 搜索推荐 算法
              【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
              本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
              101 16
              |
              2月前
              |
              算法
              分享一些提高二叉树遍历算法效率的代码示例
              这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
              |
              2月前
              |
              存储 缓存 算法
              如何提高二叉树遍历算法的效率?
              选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
              65 5
              |
              2月前
              |
              C语言
              【数据结构】二叉树(c语言)(附源码)
              本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
              139 8
              |
              2月前
              |
              算法
              树的遍历算法有哪些?
              不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
              40 2