学习笔记:树和二叉树的初步学习2

来源:互联网 发布:查莉娅伤害数据 编辑:程序博客网 时间:2024/05/01 21:54

三、树和森林

1、树的存储结构

常用的链表结构:

a.双亲表示法

以一组连续空间存储树的结点,同时,结点结构中附设一个指示其双亲结点在链表中的位置的指示器。

#define MAX_TREE_SIZE 50typedef struct PTNode{TElemType data;int parent;  //双亲位置}PTNode; typedef struct{PTNode nodes[MAX_TREE_SIZE];int r,n;   //根的位置和结点数}PTree;

这种存储结构利用了除根结点以外的每个结点只有一个双亲的性质,Parent(T,x)函数可找到其双亲。反复调用Parent函数,直到遇到无双亲的结点时,便找到了树的根。

在这种表示法中,求结点的孩子时很不方便。

2、孩子表示法

这种表示方法是把每个结点的孩子结点排列起来,看成是一个线性表,每个孩子结点以单链表作为存储结构,则n个结点有n个孩子链表(叶子结点的孩子链表为空表)。而n个头指针又组成一个线性表,为了便于查找,采用顺序存储结构。

typedef struct CTNode{  //孩子结点int child;struct CTNode *next;}*ChildPtr;typedef struct{  TElemType data;ChildPtr firstchild;   //孩子链表头指针}CTBox;typedef struct{CTBox nodes[MAX_TREE_SIZE];int n,r;   //结点数和根的位置}CTree;

这种表示法便于实现关于结点孩子的操作。

可以把双亲表示法和孩子链表结合起来,可以实现关于两头的操作。


c.孩子兄弟表示法

此又称为二叉链表表示法。链表中每个节点有两个链域,分别指向该结点的第一个孩子结点和下一个兄弟结点。

这样,将树转化为二叉树,以二叉链表形式存储。

typedef struct CSNode{ElemType data;struct CSNode *firstchild,*nextsibling;  //两个链域}CSNode,*CSTree;

给定一棵树,可以找到唯一的一棵二叉树与之对应。从物理结构方面,它们的二叉链表是相同的,只是域的名称不同、解释不同而已。

任何一颗和树对应的二叉树,其右子树必空。


2.森林与二叉树的转换

按照树与二叉树的对应关系,将森林中第二棵树的根结点看成是第一棵树的根结点的兄弟,那么,森林也可转化为二叉树。

这时的二叉树有右子树。

森林和树的操作可转换为二叉树的操作。


3.树和森林的遍历

两种遍历树的方法:

一种是先根(次序)遍历树。即先访问树的根结点,然后依次先根遍历根的每棵子树。

另一种是后根(次序)遍历,即先依次后根遍历每棵子树,再访问根结点。


森林由三部分组成:①第一棵树的根节点;②第一棵树的子树森林;③除第一棵树以外的其他树构成的森林。

按照森林和树相互递归的定义,可推出森林的两种遍历方法:先序遍历和中序遍历。


遍历对应关系:

树的先根遍历<——>二叉树先序遍历<——>森林先序遍历

树的后根遍历<——>二叉树中序遍历<——>森林中序遍历

注意:森林的中序遍历指依次从左至右对森林中每棵树进行后根遍历。


借用二叉树的先序和中序遍历算法可实现遍历树和森林。因此二叉树的遍历是很重要的。


四、赫夫曼树

赫夫曼树又称最优树,是一类带权路径长度最短的树。

1、最优二叉树

路径上的分支数目称为路径长度。

树的路径长度:从树根到每一结点的路径长度之和。

树的带权路径长度:树中所有叶子结点的带权路径长度之和。

带权路径长度最小的二叉树称作最优二叉树或赫夫曼树。

2、赫夫曼编码

进行快速远距离通信时,将需传送的文字转换成由二进制的字符组成的字符串,并且总长尽可能短,以提高传送效率。

可以对每个字符设计长短不同的编码,让电文中出现次数角度的字符采用尽可能短的编码,则电文总长可大大减少。

要设计长短不等的编码,必须是任一个字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。

设计电文总长最短的二进制前缀编码,即为设计一颗赫夫曼树的问题,权值为n种字符出现的频率。每条路径形成的编码为赫夫曼编码。


总结:二叉树的遍历是重中之重。学会树和森林与二叉树的转换。



0 0