数据结构与算法 —— 树(相关知识回顾)

一. 概述

树的存储结构应用范围极为广泛,我所了解的,如Linux操作系统的目录结构,DNS域名的存储,多路复用中的epoll利用的红黑树…
那么,什么是树嘞?
在这里插入图片描述

这就是一颗树,下面引出一些概念

  • 空树

上面的每一个圆圈表示一个结点,用n来表示结点个数,当n等于0是则代表树是空树

  • 根节点

当n>0时,树有且仅有一个根节点,如图一所示的A结点

  • 结点关系

A是B的双亲结点,B是A的孩子结点,B,C是兄弟,E,F是兄弟

  • 树的度

也是树的宽度,即结点的分支树的个数,如图一中A结点的度为3,B结点的度为2;以组成该树各节点中最大的度作为树的度,图一树的度为3,树种度为0的结点称为叶子结点或终端结点,度不为0的结点称为分支结点或非终端结点,除终端结点外的分支结点称为内部结点

  • 树的深度

组成该树各结点的最大层次,图中的树深度为4
在这里插入图片描述

  • 森林

若干颗互不相交的树的集合{T1,T2,T3}

在这里插入图片描述

  • 有序树

如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树

二. 树的实现

前面学习了顺序存储结构,链式存储结构,树的实现也需要用到二者,只是,对于树来说,又有三种表示法,分别是双亲表示法,双亲孩子表示法,孩子兄弟表示法,下面就通过树的实现来体会这些名字的由来.

2.1 双亲表示法

双亲表示法,即以双亲结点为索引的个关键词的一种存储方式,下面来看利用顺序存储的实现:

我们假设以一组连续空间存储树的结点,同时在每个结点中,即存储了本节点的值,还存储了双亲结点的位置,也就是说结点除了知道“我是谁”,还知道“我的双亲是谁”。

#define MAX_TREE_SIZE 100

typedef int ElemType;

typedef struct PTNode
{
    ElemType data;    //存储结点的数据
    ElemType parent;  //存储双亲结点的下标
}PTNode;

typedef struct
{
    PTNode nodes[MAX_TREE_SIZE];  //存储结点的数组
    int r;  //根的位置
    int n;  //结点个数
}PTree;

来看下面这颗树:
在这里插入图片描述
再来看用我们上述方法表示的结果:
在这里插入图片描述
需要注意,这里是按照层次遍历来表示的(关于遍历方式后面博客会继续总结)

想象一下,既然是结构体,我们还可以存储更多东西,例如在结点的结构体PTNode中接入孩子结点的位置,加入兄弟结点的位置,只要是便于树的操作,完全可以开放性的设计!

2.2 双亲孩子表示法

结合双亲表示法,利用链式存储,则有下面结构
在这里插入图片描述
分析完图六,我们再来看双亲孩子表示法的实现:

#define MAX_TREE_SIZE 100

typedef char ElemType;

typedef struct CTNode
{
    int     child;  //孩子结点的下标
    struct  CTNode *next;  //指向孩子的指针
}*ChildPtr;

typedef struct ctbox
{
    ElemType  data;   //结点数据
    int       parent;   //结点下标
    ChildPtr  firstchild;  //指向第一个孩子的指针
}CTBox;

typedef struct pcTree
{
    CTBox nodes[MAX_TREE_SIZE];
    int r;
    int n;
}PCTree;

关于树的其他知识,后续继续总结!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章