• 数据结构之树


    树(tree)

    • 定义

        树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做 “树” 是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。树结构是一种非线性存储结构,存储的是具有“一对多”关系的数据元素的集合

                     

     

    • 树的特点

        每个节点有零个或多个子节点;

       没有父节点的节点称为根节点;

       每一个非根节点有且只有一个父节点;

       除了根节点外,每个子节点可以分为多个不相交的子树;

    • 二叉树

        二叉树是树类结构中最常见的,也是运用最广泛的,二叉树是一种比较有用的折中方案,它添加,删除元素都很快,并且在查找方面也有很多的算法优化,所以,二叉树既有链表的好处,也有数组的好处,是两者的优化方案,在处理大批量的动态数据方面非常有用。它具有以下几个特点:

         每个结点最多有两颗子树,结点的度最大为2。 

         左子树和右子树是有顺序的,次序不能颠倒。 

         即使某结点只有一个子树,也要区分左右子树。

         二叉树中,第 i 层最多有 2i-1 个结点。

         如果二叉树的深度为 K,那么此二叉树最多有 2K-1 个结点。

                  

    • 满二叉树和完全二叉树

        满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。

                   

        满二叉树具有以下性质

         满二叉树中第 n 层的节点数为 2n-1 个。

         深度为 k 的满二叉树必有 2k-1 个节点 ,叶子数为 2k-1

         满二叉树中不存在度为 1 的节点,每一个分支点中都两棵深度相同的子树,且叶子节点都在最底层。

         具有 n 个节点的满二叉树的深度为 log2(n+1)。

       完全二叉树:如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。

                  

       完全二叉树的性质

          满二叉树中第 n 层的节点数为 2n-1 个。

          深度为 k 的满二叉树必有 2k-1 个节点 ,叶子数为 2k-1

          n 个结点的完全二叉树的深度为 ⌊log2n⌋+1。

    • 二叉树的遍历

        先序遍历:

            访问根节点;

            访问当前节点的左子树;

            若当前节点无左子树,则访问当前节点的右子树;

                  

     

           先序遍历具体过程:   

        1. 访问该二叉树的根节点,找到 1;
        2. 访问节点 1 的左子树,找到节点 2;
        3. 访问节点 2 的左子树,找到节点 4;
        4. 由于访问节点 4 左子树失败,且也没有右子树,因此以节点 4 为根节点的子树遍历完成。但节点 2 还没有遍历其右子树,因此现在开始遍历,即访问节点 5;
        5. 由于节点 5 无左右子树,因此节点 5 遍历完成,并且由此以节点 2 为根节点的子树也遍历完成。现在回到节点 1 ,并开始遍历该节点的右子树,即访问节点 3;
        6. 访问节点 3 左子树,找到节点 6;
        7. 由于节点 6 无左右子树,因此节点 6 遍历完成,回到节点 3 并遍历其右子树,找到节点 7;
        8. 节点 7 无左右子树,因此以节点 3 为根节点的子树遍历完成,同时回归节点 1。由于节点 1 的左右子树全部遍历完成,因此整个二叉树遍历完成;

         先序遍历的最终结果为:1,2,4,5,3,6,7

          中序遍历:

            访问当前节点的左子树;

            访问根节点;

            访问当前节点的右子树

                  

          中序遍历具体过程:     

        1. 访问该二叉树的根节点,找到 1;
        2. 遍历节点 1 的左子树,找到节点 2;
        3. 遍历节点 2 的左子树,找到节点 4;
        4. 由于节点 4 无左孩子,因此找到节点 4,并遍历节点 4 的右子树;
        5. 由于节点 4 无右子树,因此节点 2 的左子树遍历完成,访问节点 2;
        6. 遍历节点 2 的右子树,找到节点 5;
        7. 由于节点 5 无左子树,因此访问节点 5 ,又因为节点 5 没有右子树,因此节点 1 的左子树遍历完成,访问节点 1 ,并遍历节点 1 的右子树,找到节点 3;
        8. 遍历节点 3 的左子树,找到节点 6;
        9. 由于节点 6 无左子树,因此访问节点 6,又因为该节点无右子树,因此节点 3 的左子树遍历完成,开始访问节点 3 ,并遍历节点 3 的右子树,找到节点 7;
        10. 由于节点 7 无左子树,因此访问节点 7,又因为该节点无右子树,因此节点 1 的右子树遍历完成,即整棵树遍历完成;

            中序遍历的最终结果为:4,2,5,1,6,3,7

          后序遍历:

            从根节点出发

            依次遍历各节点的左右子树,

            直到当前节点左右子树遍历完成后,才访问该节点元素。

                      

          后序遍历具体过程:

        1. 从根节点 1 开始,遍历该节点的左子树(以节点 2 为根节点);
        2. 遍历节点 2 的左子树(以节点 4 为根节点);
        3. 由于节点 4 既没有左子树,也没有右子树,此时访问该节点中的元素 4,并回退到节点 2 ,遍历节点 2 的右子树(以 5 为根节点);
        4. 由于节点 5 无左右子树,因此可以访问节点 5 ,并且此时节点 2 的左右子树也遍历完成,因此也可以访问节点 2;
        5. 此时回退到节点 1 ,开始遍历节点 1 的右子树(以节点 3 为根节点);
        6. 遍历节点 3 的左子树(以节点 6 为根节点);
        7. 由于节点 6 无左右子树,因此访问节点 6,并回退到节点 3,开始遍历节点 3 的右子树(以节点 7 为根节点);
        8. 由于节点 7 无左右子树,因此访问节点 7,并且节点 3 的左右子树也遍历完成,可以访问节点 3;节点 1 的左右子树也遍历完成,可以访问节点 1;
        9. 到此,整棵树的遍历结束。

            后序遍历最终结果:4,5,2,6,7,3,1

          层次遍历:

            通过使用队列的数据结构,从树的根结点开始,依次将其左孩子和右孩子入队。而后每次队列中一个结点出队,都将其左孩子和右孩子入队,直到树中所有结点都出队,出队结点的先后顺序就是层次遍历的最终结果。

                      

          层次遍历具体过程:

        1. 首先,根结点 1 入队;
        2. 根结点 1 出队,出队的同时,将左孩子 2 和右孩子 3 分别入队;
        3. 队头结点 2 出队,出队的同时,将结点 2 的左孩子 4 和右孩子 5 依次入队;
        4. 队头结点 3 出队,出队的同时,将结点 3 的左孩子 6 和右孩子 7 依次入队;
        5. 不断地循环,直至队列内为空。

            层次遍历最终结果:1,2,3,4,5,6,7

         

  • 相关阅读:
    内存映射函数remap_pfn_range学习——代码分析(3)
    内存映射函数remap_pfn_range学习——示例分析(2)
    内存映射函数remap_pfn_range学习——示例分析(1)
    在busybox里使用ulimit命令
    unlocked_ioctl和compat_ioctl
    使用cat读取和echo写内核文件节点的一些问题
    如何成为强大的程序员?
    如何实现“秒杀”系统
    关于博客园代码样式的调整
    Consuming a RESTful Web Service
  • 原文地址:https://www.cnblogs.com/javaisbest/p/12931730.html
Copyright © 2020-2023  润新知