【笔记】树的表示与实现
来源:互联网 发布:手机收发邮件软件 编辑:程序博客网 时间:2024/06/02 06:03
- 树的抽象数据型
- 树的表示
- 树的数组表示
- 树的邻接表表示
- 树的左右链表示法
- 树的实现
1.树的抽象数据型
与二叉树一样,在树上规定如下基本操作,可以把树定义成抽象数据型。
- Parent(n,T):返回树T结点n的父亲。若n是根,则返回空。
- LeftMostChild(n,T):返回树T结点的最左儿子。
- RightSibling(n,T):返回树T结点n的右兄弟。
- Data(n,T):返回树T结点n的DATA域的值。
- Create(
v,T1,T2,…,Tk ):建立DATA域为v的根结点r,此结点有k颗子树T1,T2,…,Tk ,且T1,T2,…,Tk 是自左而右排列的。返回以r为根的树;若k=0,则r既是根也是叶结点。- Root(T):返回树T的根结点。
通常可以对树定义3种遍历顺序,假设各子树记为
(1)先根顺序
- 访问根结点。
- 先根顺序遍历
T1 - 先根顺序遍历
T2
… - 先根顺序遍历
Tk - 退出
(2)中根顺序
- 中根顺序遍历
T1 - 访问根结点。
- 中根顺序遍历
T2
… - 中根顺序遍历
Tk - 退出
(3)后根顺序
- 后根顺序遍历
T1 - 后根顺序遍历
T2
… - 后根顺序遍历
Tk - 访问根结点。
- 退出
树的先根遍历算法:
void PreOrder(node n,TREE T)/*按先根顺序列出树T中结点n及其所有后代的数据域的值*/{ node c; visit(Data(n,T)); c=LeftMostChild(n,T); while(c!=NULL) { PreOrder(c,T); c=RightSibling(c,T); }}
如果要按先跟顺序遍历整棵树T,则只要调用PreOrder(Root(T),T)即可。
2.树的表示
树的数组表示
设T是一棵树,其中的结点命名为1,2,3,…,n。根据树中每个结点只有一个父亲这个特性,可用数组A来表示树T。令数组的下标对应于结点名,数组元素A[i]定义如下:
这种表示法除根结点外,每个结点只有一个指向其父亲结点的链域。所以有时把这种表示法称为树的父链表示法或单链表示法。
一般来说,Parent(i)=A[i]。数组元素由parent和data两个域构成。可以把上图表示的树的结构描述为:
struct node{ int parent; char data;};typedef node TREE[11];TREE T;
这种只有父链的表示方法,对于求父结点及祖先结点都很方便。但对于给定的结点n,欲求其子结点的信息相当困难,也不能反映各兄弟结点的顺序。但是如果在给结点命名时,可按照这样一种顺序:对每个结点n,在对n进行编号之后,按自左而右递增的顺序依次对n的儿子进行编号。在此假设之下,将很容易实现RightSibling和LeftMostChild。
typedef int node;typedef node TREE[maxnodes];node LeftMostChild(node n,TREE T){ node i; for(i=n+1;i<=maxnodes-1;i++) if(T[i]==n) return i; return 0;}
树的邻接表表示
树的一种重要表示法是每个结点的所有子结点形成一个线性表,但因每个结点所具有的子结点个数不同,所以通常都采用链接式表示。
上图中的树为例可以表示为下图所示。其中有一个数组header,每一个数组元素header[i]是一个表头结点,指向结点i的儿子结点链表的首结点。对于每个结点i,由header[i]出发,可以很容易地将其全部儿子结点找到。
邻接表的类型说明:
typedef int node;struct celltype{ node element; celltype *next;};typedef celltype *LIST;typedef celltype *position;struct TREE{ LIST header[maxnodes]; datatype data[maxnodes]; node root;};
用树的这种表示法实现LeftMostChild操作:
node LeftMostChild(node n ,TREE T){ LIST L; L=T.header[n]; if(Empty(L)) return 0; else return(Retrieve(First(L),L));}
树的左右链表示法
通常,可以按照其自然形式,令每个结点除其信息域外,设置多个链域,使它们指向相应的儿子结点,但这样会使每个结点占用的空间较多。为了节省每个结点所占用的空间,在每个结点中只设置两个链域,令左链指向最左儿子,右链指向紧挨它的右兄弟,树的这种存储表示方法称为树的左右链表示法,也称为树的左兄弟右儿子表示法或者树的二叉链表表示法。这种表示法很容易实现由较小的树来构造较大的树。
其存储结构为:
struct { datatype data; int leftchild; int rightsibling;}cellspace[maxnodes];
用树的左右链表示法,很容易实现除Parent操作以外的各种操作。如果希望有效地实现Parent操作,即快速地找到一个结点的父结点,则在每个结点中增加指向父结点的链域。
struct{ datatype data; int leftchild; int rightsibling; int parent;}cellspace[maxnodes];
此外,还可以选择这样一种结构:令最右儿子的rightsibling域指向右父亲,于是必须对每个结点增加一个标志位,用于区别其rightsibling域是指向兄弟还是指向父亲。在求一个结点的父亲时,只需沿着rightsibling域查到虚线的指向即可。这比在每一个结点中增加parent域可节省控件,但花费的时间稍多一些。
- 树不能为空的理由
如果在设计的体系中定义了森林,同伙私又允许树为空, 那么由于森林是由若干颗树构成的,很可能出现一个集合(森林)包含许多空集(树),或者一个空集(森林)包含许多个空集(树)的情况。如果允许树为空,则很难确定森林中的一颗空树对应于什么样的二叉树,两颗空树对应于什么样的二叉树。
3.树的实现
源码参见树的实现
- 【笔记】树的表示与实现
- 二叉树的存储表示与实现
- 栈的表示与实现
- 单链表的表示与实现
- 队列的表示与实现
- 数据结构与算法分析笔记与总结(java实现)--字符串4:表示数值的字符串
- 树的父指针表示与Union/Find算法实现
- 浅谈二叉树的存储表示与实现
- c语言二叉树的存储表示与实现
- <数字图像处理的MATLAB实现笔记>第11章 表示与描述(一)
- <数字图像处理的MATLAB实现笔记>第11章表示与描述(二)
- 线性表的链式表示与实现
- 抽象数据类型的表示与实现
- 线性表的链式表示与实现
- 数组的顺序表示与实现
- 链栈的表示与实现
- 数组的顺序表示与实现
- 线性表的顺序表示与实现
- 【util】MappedByteBuffer按行读取的方案
- 智能指针与弱指针解决循环引用
- 浅谈SQL Server中的三种物理连接操作
- Collections 源码分析
- 第七篇 elasticsearch如何解决并发冲突问题
- 【笔记】树的表示与实现
- p60-4.3(4)
- ZOJ 1078
- 神经网络 数字可视化
- python 重建二叉树的三个方法
- grid测试
- AIX增加内存需要IBM下单才能识别
- 实验4 析构函数 对象数组与指针
- VMware Workstation下VMnet1等虚拟网卡与主机网卡之间的关系学习