《大话数据结构》第六章 树

本文详细介绍了树的定义、树的抽象数据类型以及多种存储结构,包括双亲表示法、孩子表示法和孩子兄弟表示法。接着探讨了二叉树的特性、遍历方法(前序、中序、后序和层序遍历)以及特殊类型的二叉树。文章还讨论了线索二叉树的构建与遍历,以及树与森林、二叉树之间的转换。此外,还涉及赫夫曼树及其在提高传输效率中的应用。
摘要由CSDN通过智能技术生成


第六章 树

树的定义

树的定义:树(Tree)是n个结点的有限集,n=0时称为空树。在任意一棵非空树中:

  1. 有且仅有一个特定的根(Root)的结点
  2. 当n>1时,其余的结点可分为m个互不相交的有限集 T 1 , T 2 , . . . T m T_1,T_2,...T_m T1,T2,...Tm,其中每一个集合本身优势一棵树,并且称为根的子树(SubTree)


错误的树
子树相交了


结点的分类

结点的度:结点拥有的子树树被称为结点的度(Degree)。

叶结点/终端结点:度为0的结点称为叶结点(Leaf)或终端结点。

非终端结点/分支结点:度不0的结点。

内部结点:除了根结点之外,分支结点也称为内部结点。

树的度:树内各结点的度的最大值。

结点间关系

  1. 结点的子树的根称为该结点的孩子(Child),相应地,该节点称为孩子的双亲(Parent)。
  2. 同一个双亲的孩子之间互称兄弟(Sibling)。
  3. 结点的祖先是从根到该结点所经分支上的所有结点。
  4. 以某结点为根的子树中的任意结点都称为该节点的子孙。

树的其他相关概念

  • 结点的层次(Level)从根开始定义起,根为第一层,根的孩子为第二层。
  • 双亲在同一层的结点互为堂兄弟
  • 树中结点的最大层次称为树的深度(Depth)或高度。深度是绝对的,从根结点开始算,高度是相对的,看自己的子树有多高。
  • 如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则为无序树
  • 森林(Forest)是m棵互不相交的树的集合,对树中的每个结点而言,其子树的集合即为森林



树的抽象数据类型


树的存储结构

利用顺序存储和链式存储结构的特点,完全可以实现对树的存储结构的表示

双亲表示法

思路:在每个结点中,附设一个指示器指示其双亲结点到链表中的位置,知道爹妈是谁,不知道孩子是谁(段正淳?)。

结点结构定义

#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode    // 结点结构
{
   
    TElemType data;    // 结点数据
    int parent;    // 双亲位置
} PTNode;

typedef struct    // 树结构
{
   
    PTNode nodes[MAX_TREE_SIZE];
    int r, n;    // 根的位置和结点数
} PTreee;

根节点没有双亲,所以约定根结点的位置域设置为-1。

可以根据需求,再增加一个结点最左边孩子的域,叫长子域,如果没有孩子结点,长子域设置为-1:

还可以增加右兄弟域,如果存在右兄弟,就记录下右兄弟的小标,不存在就设置为-1:

那么左右是怎么确定的呢?


孩子表示法

多重链表表示法:由于树中每个结点可能有多棵子树,可以考虑用多重链表,即每个结点有多个指针域,其中每个指针指向一棵子树的根结点,我们把这张方法叫做多重链表表示法。

然而树的每个结点的度是不同的,有两种解决方案。

方案一:
让指针域的个数就等于树的度:

其中data是数据域,child1到childd是指针域,用来指向该结点的孩子结点。

缺点:但是这样很浪费空间,除非说各个树的结点度相差很小的时候,才有优势。

方案二
每个指针结点域的个数等于该结点的度,专门取一个位置来存储结点指针域的个数:

其中data为数据域,degree为度域,也就是存储该结点的孩子结点的个数,child1到childd为指针域,指向该结点的各个孩子的结点。

缺点:虽然对空间的利用率提高了,但是由于各个结点的链表是不相同的结构,加上要维护结点的度的数值,在运算上就会带来时间上的损耗。

孩子表示法:把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空,然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中

分而治之?

孩子链表的孩子结点

其中child是数据域,用来存放结点在表头数组中的下标;next是指针域,存放指向某结点的下一个孩子结点的指针。

表头数组的表头结点


其中data是数据域,存储某结点的数据信息;firstchild是头指针域,存储该结点的孩子链表的头指针

孩子表示法结构定义

#define MAX_TREE_SIZE 100
typedef struct CTNode
{
   
    int child;    // 表头下标
    struct CTNode *next;
} *ChildPtr;
typedef struct CTBox   // 表头结构
{
   
    TElemType data;
    ChildPtr firstchild;
};
typedef struct CTree   // 树结构
{
   
    CTBox nodes[MAX_TREE_SIZE];    // 表头结构数组,就是结点数组
    int r, n;    // 根的位置和结点数
};

优点:对于查找某个结点的某个孩子,或者找某个结点的兄弟,遍历等比较方便

感觉兄弟不好找呀,比如找A的兄弟,要遍历找到包含A的子链表,才能找到A的兄弟

缺点:无法找到双亲,找双亲需要遍历。

所以可以把双亲表示法和孩子表示法综合一下,得到双亲孩子表示法


孩子兄弟表示法

理论基础:任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的,因此,设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟。

其中data是数据域;firstchild为指针域,存第一个孩子的地址;righsib也是指针域,存储右兄弟结点的地址。

结构定义代码

typedef struct CSNode
{
   
    TElemType data;
    struct CSNode *firstchild, *rightsib;
} CSNode, *CSTree;

如果有需要可以加parent指针域。

好处:给查找某个结点的孩子带来了方便,同时把一棵复杂的树变成了一棵二叉树


二叉树

定义:二叉树是n个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成

二叉树特点

  • 每个结点最多两棵子树,所以二叉树中不存在度大于2的结点。
  • 左子树和右子树是有顺序的,次序不能任意颠倒。
  • 即使某结点只有一棵子树,也要区分他是左子树还是右子树

二叉树的五种基本形态

  1. 空二叉树
  2. 只有一个根结点
  3. 根结点只有左子树
  4. 根结点只有右子树
  5. 根结点既有左子树又有右子树

三个结点的二叉树有五种形态


特殊二叉树

斜树

定义:所有的结点都只有左子树的二叉树叫左斜树,只有右子树叫右斜树,这两者统称为斜树。

左斜树

右斜树

特点:每一层都只有一个结点,结点的个数与二叉树的深度相同。


满二叉树

定义:在一棵二叉树中,如果所有的分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树被称为满二叉树

特点

  1. 叶子只能出现在最下层
  2. 非叶子结点的度一定是2
  3. 在同深度的二叉树中,满二叉树的节点个数最多,叶子数最多

完全二叉树

定义:对一棵具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点的位置,和同深度的满二叉树中 i 结点的位置相同,那这颗树就叫完全二叉树。

没满,但是存在的结点结构和满二叉树相同

按层序编号后的结点应连贯,满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树,下面是非完全二叉树

特点

  1. 叶子结点只能出现在最下两层
  2. 最下层的叶子一定集中在左部连续位置
  3. 倒数二层,若有叶子结点,一定都在右部连续位置
  4. 如果结点度为1,则该结点只有左孩子,不存在只有右孩子的情况
  5. 同样结点树的二叉树,完全二叉树的深度最小

子树的生成以左边为主,但是不可只有左边,倒数第二层必须有右边,倒数第二层开始网上必须都完全填满,所以深度会最小


二叉树的性质

性质1:在二叉树的第 i 层上至多有 2 i − 1 2^{i-1} 2i1个结点(i>=1)

性质2:深度为k的二叉树至多有 2 k − 1 2^{k}-1 2k1个结点(k>=1)

性质3:对任何一棵二叉树T,如果其终端结点数位 n 0 n_0 n0,度位2的结点数为 n 2 n_2 n2,则 n 0 = n 2 + 1 n_0 = n_2 + 1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值