数据结构树和森林的表示和遍历
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
森林和二叉树的对应关系
T1
root
T2,…,Tn
T11,T12,…,T1m
LBT
RBT
森林和二叉树的对应关系
由森林转换成二叉树的转换规则为: 若 F = Φ,则 B = Φ; 否则,
由 ROOT( T1 ) 对应得到Node(root); 由 (t11, t12, …, t1m ) 对应得到 LBT; 由 (T2, T3,…, Tn ) 对应得到 RBT。
孩子链表表示法
A BCD
EF G
data firstchild
0A
1
1B
2C
4
3D
4E
5F
6
6G
23 5
root=0 n=7
孩子链表表示法
C语言的类型描述: 孩子结点结构: child nextchild
typedef struct CTNode { int child; struct CTNode *nextchild;
A BCD
EF G
data
0A 1B 2C 3D 4E 5F 6G
parent -1 0 0 0 2
2 5
root=0 n=7
双亲表示法
C语言的类型描述: #define MAX_TREE_SIZE 100
结点结构: data parent
typedef struct PTNode {
TElemType data;
int
parent; // 双亲位置域
} PTNode;
双亲表示法
树结构:
typedef struct { PTNode nodes[MAX_TREE_SIZE]; int r, n; // 根结点的位置和结点个数
} PTree;
孩子链表表示法
1.多重链表:每个结点有多个指针域,分别 指向其子树的根
A
BCD
EF G
A B
E
C
F
D
G
树的遍历的应用
二、输出树中所有从根到叶子的路径的算法:
A
对左图所示的树,其输出结果
B C D 应为: A B E
EF
G
ABF AC
H
ADGHI
I JK
ADGHJ
ADGHK
树的遍历的应用
对树先根遍历(深度优先) 1、T为空,栈中存放的是从根到T的父结点的路径 2、将T压栈,栈中存放的是从根到T的路径 3、递归访问T的子树 4、将T出栈
树的遍历的应用
void AllPath( CSTree T, Stack& S ) {//树的先根遍历
if(!T) {PrintStack(S), return} Push( S, T->data );//树根压栈 p=T->firstchild//T的第一颗子树 while(p) {//T的所有子树
森林的遍历-先序遍历
A
F
B C DD G
H I JJ
森林对应的二叉树:
A
B
F
E
KK
先根遍历序列为:
ABCDEFG HIKJ
CG H DI
EE K J
森林的遍历-中序遍历
森林不空,则 中序遍历森林中第一棵树的子树森林;
访问森林中第一棵树的根结点; 中序遍历森林中(除第一棵树之外)其余树构 成的森林。 即:依次从左至右对森林中的每一棵树进行 后根遍历。
}
树的遍历的应用
int Depth(CSTree T){//二叉链表作为存储结构
if (!T) return 0;//空树
A
p=T->firstchild; d=0; while(p){//依次求子树的深度
BCD
d1 = Depth(p);
EF G
if(d1>d) d=d1; p=p->nextsibling; }
树和森林的表示方法和遍历
树的表示方法 森林和二叉树的对应关系 树和森林的遍历 小结和作业
树的存储结构
一、双亲表示法 二、孩子链表表示法 三、带双亲的孩子链表表示法 四、树的孩子兄弟表示法
双亲表示法
用一组连续空间存储树的结点,同时在每 个结点中附设一个指示器指示其双亲结点 在链表中的位置。
双亲表示法
结点结构: firstchild data nextsibling
指向第一个孩子 结点
指向下一个兄弟 结点
树的孩子兄弟存储表示法
C语言的类型描述:
typedef struct CSNode{ TElemType data; struct CSNode *firstchild,*nextsibling;
EF G
3、从所有子树的深度中取最大,然后加1,即 为树的深度
树的遍历的应用
int Depth(Tree T){//只考虑逻辑结构 if(!T) return(0); for(p=T1,T2,…Tn){//每棵子树 d[p]=Depth(p) a=max(d[1],d[2],…d[n]) return(a+1)
森林和二叉树的对应关系
2.将得到的二叉树全部还原成树
A
E
B
F
C
D
G H
I J
A
E
G
B C DFH I
J
森林和二叉树的对应关系
由树、森林和二叉树的相互转换可知,树和森林 的各种操作均可与二叉树的各种操作相对应。 不过,和树对应的二叉树,其左、右子树的概 念已改变为: 左子树是孩子,右子树是兄弟。
树和森林的遍历
} *ChildPtr;
孩子链表表示法
双亲结点结构 data firstchild
typedef struct { TElemType data; ChildPtr firstchild;
// 孩子链的头指针 } CTBox;
孩子链表表示法
树结构: typedef struct { CTBox nodes[MAX_TREE_SIZE]; int n, r; // 结点数和根结点的位置 } CTree;
} CSNode, *CSTree;
树的孩子兄弟存储表示法
root
A
A
A
B CD EF
B
C
E
D
B C
G
F
E
D
G
F
G
森林和二叉树的对应关系
树与二叉树的对应关系:给定一棵树,通 过树的二叉链表表示法可以找到唯一的一 棵二叉树与之对应。树的二叉链表的右子 树一定是空的。 森林与二叉树的对应关系:将森林中的第 二棵树看成第一棵树的兄弟即可。
后根(次序)遍历序列为:
E F BCI J K H G DA
A
BB C D
EF
G
H
I JJ K
树的遍历-按层次遍历
按层次遍历:若树不空,则自上而下自左至右 访问树中每个结点。
按层次遍历序列为:
A B C DE F GH I J K
A BB C D
EF
G
H
I JJ K
树的遍历
A
A
树的二叉树表示: B
printStack(S);
Leabharlann Baidu
EF G
pop(S);} OutPath(T->firstchild, S ); OutPath( T->nextsibling, S );
A B
E
C
}利用二者的先序遍历结果相同
F
D
G
树的遍历的应用
三、建立树的存储结构的算法:
和二叉树类似,不同的定义相应有不同的算 法。 假设以二元组(F,C)的形式自上而下、自左而右 依次输入树的各边,建立树的孩子-兄弟链表。
森林和二叉树的对应关系
森林转换成二叉树:先将森林中的所有树转换成
二叉树
A
E
G
A B
E F
G H
B C DFH
I
C
I
J
D
J
森林和二叉树的对应关系
以第一棵二叉树的根为树根,将森林中所有的 二叉树转换成一棵二叉树
A
E
G
A
B
F
C
D
H I
J
B
E
CF
G
DH
I
J
森林和二叉树的对应关系
由二叉树转换为森林的转换规则为: 若 B = Φ, 则 F = Φ; 否则, 由 Node(root) 对应得到 ROOT( T1 ); 由LBT 对应得到 ( t11, t12, …,t1m); 由RBT 对应得到 (T2, T3, …, Tn)。
一、树的遍历 二、森林的遍历 三、树的遍历的应用
树的遍历-先根(次序)遍历
先根(次序)遍历:若树不空,则先访问根结 点,然后依次先根遍历各棵子树。
先根(次序)遍历序列为:
A BEFCDGHIJK
A BB C D
EF
G
H
I JJ K
树的遍历-后根(次序)遍历
后根(次序)遍历:若树不空,则先依次后根遍 历各棵子树,然后访问根结点。
带双亲的孩子链表表示法
1.双亲表示法,PARENT(T,x)可以在常量时 间内完成,但是求结点的孩子时需要遍历整个结 构。 2.孩子链表表示法,适于那些涉及孩子的操作, 却不适于PARENT(T,x)操作。 3.将双亲表示法和孩子链表表示法合在一起,可以 发挥以上两种存储结构的优势,称为带双亲的孩子 链表表示法
一、求树的深度
TElemType data; struct CSNode *firstchild,
*nextsibling; } CSNode, *CSTree;
二、输出树中所有从 根到叶子的路径
三、建立树的存储结构
树的遍历的应用
一、求树的深度的算法:
A
1、如果T为空,则树的深度为0
BCD
2、求出T每棵子树的深度
BCD
E
C
EF G 树先根遍历 ABEFCDG
F
D
G
因此,树的先根遍历结果与其对应二叉 树表示的先序遍历结果相同
树的遍历
A
A
树的二叉树表示: B
BCD
E
C
EF G
F
D
树后根遍历 EFBCGDA
G
因此,树的后根遍历结果与其对应二叉
树表示的中序遍历结果相同
森林的遍历
B CD
EF
G
H
森林可以分解成三部分:
带双亲的孩子链表表示法
A BCD
EF G
Parent data firstchild
0 -1 A
1
10 B
20 C
4
30 D
42 E
52 F
6
65 G
23
5
root=0 n=7
树的孩子兄弟存储表示法
A B CD
EF G
A
B
C
E
D
F
G
树的孩子兄弟存储表示法
又称为二叉树表示法,以二叉链表作为树的 存储结构。
森林的遍历-中序遍历
A
F
B C DD G
H I JJ
E
KK
中序遍历序列为: B C E DAG F K I J H
A
B
F
CG H DI
EE K J
树的遍历与二叉树遍历的对应关系
树
森林
二叉树
先根遍历 先序遍历 先序遍历
后根遍历 中序遍历 中序遍历
树的遍历的应用
设树的存储结构为孩子兄弟链表
typedef struct CSNode{
AllPath( p, S ); p=p->nextsibling; } Pop(S);//访问完T的所有子树
} // AllPath
树的遍历的应用
void OutPath( CStree T, Stack& S ) {
if(!T) return;
A
Push(S, T->data );
BCD
if(!T->firstchild) {//”叶子”节点
森林和二叉树的对应关系
二叉树转换成森林
1)抹线:将二叉树中根结点与其右孩子 连线,及沿右分支搜索到的所有右孩子间 连线全部抹掉,使之变成孤立的二叉树 2)还原:将孤立的二叉树还原成树
森林和二叉树的对应关系
1.断开二叉树中右分支中搜索到的所有右孩 子间的连线
A
A
E
G
B
E
B
F
H
CF
G
C
I
DH
D
J
I
J
void CreatTree( CSTree &T ) {
T = NULL;
for( scanf(&fa, &ch);ch!=#; scanf(&fa, &ch)) {
p = GetTreeNode(ch); // 创建结点
EnQueue(Q, p); // 指针入队列
1)结点同构:结点的指针个数相等,为树的度k, 这样n个结点度为k的树必有n(k-1)+1个空链域.
data child1 child2 ………. childD
孩子链表表示法
2)结点不同构:结点指针个数不等,为该结点的 度d
data child1 child2 ………. childD
2.孩子链表:每个结点的孩子结点用单链表存 储,再用含n个元素的结构数组指向每个孩子 链表
return (d+1); }
A B
E
C
F
D
G
树的遍历的应用
int Depth(CSTree T){ if (!T) return 0; d1 = Depth(T->firstchild); d1 = d1 + 1;
d2 = Depth(T-> nextsibling); } return (max(d1,d2) );
1.森林中第一棵树的根点; 2.森林中第一棵树的子森林; 3.森林中其它树构成的森林。
I JJ K
森林的遍历-先序遍历
若森林不空,则 1)访问森林中第一棵树的根结点; 2)先序遍历森林中第一棵树的子树森林; 3)先序遍历森林中(除第一棵树之外)其 余树构成的森林。 即:依次从左至右对森林中的每一棵树进行先 根遍历。
树的遍历的应用
对左侧所示树的输入序列应为:
A
(‘#’, ‘A’)
A
B C D (‘A’, ‘B’)
B
(‘A’, ‘C’)
EF G
(‘A’, ‘D’) (‘C’, ‘E’) (‘C’, ‘F’) (‘E’, ‘G’) (‘ ‘,’#’)
C
D
可见,算法中需要一个 队列保存已建好的结点 的指针
树的遍历的应用