• 数据结构——树


    树的基本概念

    树是一种非线性的数据结构,因它的结构与倒着的树类似而得名。

    树由N个节点构成,其中最上面有一个根节点,其它的节点可以认为都是根节点的孩子。

    既然是倒过来的树,那么上图的A节点就相当于根,往下伸展最下面的就是叶子。

    树有N个节点,又是由多个结构相同的子树组成的,像上图:

     每个子树的根节点只能有一个前驱,可以有多个后驱(也可以没有)。

     并且子树之间不能有交集,否则就不是树形结构,而是另一种数据结构:图。

     像红线这里,产生了交集,这就不是树,而是图了。

    下面列举了树结构里面一些常见的概念:

     关于这里节点的层次、树的高度说明一下:

    有的书上定义层次时,将根节点A(最上面的根节点)层次定义为1,但也有的定义为0,这是两种不同的定义方式,我个人认为起始层次定义为1更好一点(原因如下)

     森林是由多棵树构成的,像并查集就是森林。

    树的表示

    要写一个树的结构就不像顺序表和链表那么简单了,因为它不是线性的,不能顺着一条线访问。

    而且节点个数不确定,这样在构造结构的时候就会比较麻烦。

     像这样不知道有多少个节点不好下手,这时我们想到可以用指针数组来封装节点。

     用一个childArr封装节点,并用childSize记录节点个数。但是这相当于是静态的树,因为它把树的度给定死了,有的节点的度是50,但有的可能只有2,就会有很多浪费,无法满足我们的需求。这时候就需要动态的。

     再用一个顺序表来存节点,需要用到二级指针,但这种结构虽然直观了一点,但是在C语言中很复杂,如果是在C++下面上个容器会清楚很多,但也不是最优的,有高手就创造了一种很好的结构(左孩子右兄弟表示法)。

     

     

     让根节点去找它的第一个子节点,让第一个子节点去找它的兄弟节点。相当于一个爹先养一个大儿,大儿再养二儿.......这样就可以找到全部节点了。

    有人可能会问,不是不能有交集吗?注意:这里是实现方式,实现方式可以任意,但是结构是不能产生交集的。我这么实现,但是结构出来是没有交集的。

    下面是一段打印整个树的伪代码:

    1. typedef struct TreeNode
    2. {
    3. struct TreeNode* child;
    4. struct TreeNode* brother;
    5. int data;
    6. }TreeNode;
    7. void TreeNodePrint(TreeNode* parent)
    8. {
    9. if (parent == NULL)
    10. return;
    11. TreeNode* cur = parent->child;//找到第一个孩子
    12. while (parent)
    13. {
    14. //printf(); 打印数据
    15. TreeNodePrint(parent);//递归调用,打印整个树
    16. cur = cur->brother;
    17. }
    18. }

    数还有一种表示法,叫双亲表示法。这种方式方便任何节点找祖先,像之前说的并查集就是这种表示法。

     

    树的实际应用

    像我们操作系统文件目录什么的就是树来实现的。

     当我们点list这个文件夹时,就类似执行上面那种伪代码(只是类似),然后就显示下一层(子节点)。

     

  • 相关阅读:
    SQL语句知识大全
    基于GBDT+Tkinter+穷举法按排队时间预测最优路径的智能导航推荐系统——机器学习算法应用(含Python工程源码)+数据集(四)
    Simple Factory Pattern 简单工厂模式简介与 C# 示例【创建型】【设计模式来了】
    uboot源码——汇编阶段的start.S文件
    【深入理解C】动态内存管理
    滨州ITSS认证流程,认证条件
    制作搞笑聊天视频的新神器,全自动搞笑聊天对话视频生成器!
    【51单片机】利用【时间延迟】的原理规避【按键抖动问题】
    撬开多线程的大门——学习多线程必须掌握的基本概念
    【AIGC】逆向拆解OpenAI官方提示词Prompt技巧:高效提升ChatGPT输出质量
  • 原文地址:https://blog.csdn.net/SAKURAjinx/article/details/126214027