5_树和二叉树
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3/65
1.1 基本概念和术语
树的 树是由n个结点构成的有限集,n=0时称作空树;n≠0时, 定义 树=唯一的根+若干子树,且每棵子树也是树。
其它
A
1、双亲(前件)、孩子(后件)、兄弟、
祖先(含双亲)、子孙(含孩子)、终
B
CD
端结点(叶子)、非终端结点(分支)、
2、树的度、结点的度、
E
F G HI
5F 1
6G 3
7H 3
8I 6
9J 6
10 K 6
要知其然,更要知其所以然。
6/65
树的存储结构:孩子数组表示法
A BC EF G
IJ
#define M 100 #define m 3 typedef struct {
char data; int c[m]; } node;
data c[0] c[1] c[2]
分析:括号表示转孩子指针表示,实质是根据括号表示建树。根 据树的定义,建树必须区分出根和子树,怎样区分?
括号表示中含:字母、"("、")"、","等字符,遇到各表示何种含义?
0、空则返回; 1、输出左括号"("; 2、输出第1个非空孩子; 3、对其余非空孩子,按:
",孩子" 形式输出; 4、输出右括号")".
while(i<m && t->c[i]==NULL) i++; if (i>=m) return; //无子则返回 printf("( "); kuohao(t->c[i]); i++; for(i=i; i<m; i++)
if (t->c[i]!=NULL){ printf(","); kuohao(t->c[i]);}
A( B, C( F,G,H), D, E(J,I) )
printf(")");
}
要知其然,更要知其所以然。
20/65
算法:括号表示转孩子指针表示
假定m度树t的括号表示存于a[0..len-1]中。
8 I -1 -1 -1
9 J -1 -1 -1
10 K -1 -1 -1
要知其然,更要知其所以然。
7/65
树的存储结构:孩子指#d针efin表e m示3 法
A
B CD
EF G
H
IJK
typedef struct k{ char data; struct k* c[m];
} tree; root
A
E^
F^
G
H^^
} tree;
I^ J^ K^^
要知其然,更要知其所以然。
10/65
1.3
遍历及线性表遍历示:所有结点逐一探测,是 很多算法的基础。
树遍历:按特定顺序访问树中每个结点一次,且仅一次。
前根遍历:空树返回;否则先访问根,再从左至右依次前序遍历根的每棵子树。
后根遍历:空树返回;否则先从左至右依次后序遍历根的每棵子树,再访问根。
二叉树 基本概念和性质 存储结构 遍历和相关算法
1. 掌握树的链式存储结构,以及树 的各种遍历算法;
2. 掌握二叉树的相关基本性质; 3. 掌握二叉树遍历的递归算法,以
及前序、中序的非递归算法、 4. 掌握二叉树与树/森林相互转换;
穿线树、二叉树和树/森林间的相互转换
要知其然,更要知其所以然。
p=出队元素;
p=outQueue(Q);
访问p;
Visit(p);
p的所有非空孩子依次入队;
p的所有孩子依次入队;
}
}
}
要知其然,更要知其所以然。
15/65
算法:输出树的凹入表示
B
E
F
A
C
D
G HI
JK
分析:
1、自上而下输出有何规律? 2、包含空格、字符、#,且每行 总长固定。空格数如何变化?
A
kuohao(t->c[i]);
printf(","); } printf(")"); }
优化使 其符合 预期。
要知其然,更要知其所以然。
19/65
算法:输出树的括号表示 void kuohao(tree *t){ int i=0;
美化输出算法思想
if (t==NULL) return; printf("%c ", t->d);
特点: "("前面的元素一定 括号表示:
A(B,C(F,G,H),D,E(J,I))
为某棵树或子树的根结点。
要知其然,更要知其所以然。
18/65
算法:输出树的括号表示 A B C DE
括号表示规则:
1、空树不表示; 2、若树t只有根,则K(t)=A; 3、否则, K(t)=A( K(T1) ,K(T2),…, K(Tm) )
iffo(frin(di=P0r;ei(<tm->;ci[+i]+,x))!=NULL ) reptuorsntTfrinadvePlr(et-(>t-c>[ci][)i;],x);
retuVrinsiNt(UtL)L; ; }}
请基于前序遍历给出查找x的递归定义。
要知其然,更要知其所以然。
12/65
假设树的度为m
preTravel( tree *t ){ if (t==NULL) return; Visit( t ); for (i=0; i<m; i++) preTravel(t->c[i]);
}
基于前序遍历衍生的查找算法
tree *findPre( tree *t, char x){
if (t==NULL) return NULL; ipf (ots-t>Tdr=a=vxe)l(rterteuern*tt);{ for i(fi=(t0=; =i<NmU;LiL+)+r)eturn;
H
IJK
#define M 100 typedef struct {
char data; int parent; } node; typedef struct { node t[M]; int length, root ; } tree;
0
data
A
parent
-1
root
1B 0
2C 0
3D 0
4E 1
m度树的前序遍历建树算法
tree * creaTree (){ int i; tree* t; char c=getchar(); if (c=='#') return NULL; t= malloc(sizeof(tree));
A
B CD
EF G
H
IJK
t->d=c; for (i=0; i<m; i++)
1B
4
2 C∧
3D
6
4 E∧
typedef struct { char data; childNode *firstChild;
} treeNode;
5 F∧
6G
8
7 H∧
8 I∧
typedef struct {
9 J∧
node treelist [M]; int length, root;
10 K ∧
D
root 0 A 1 2 3
H
1 B 4 5 -1 2 C -1 -1 -1
K
3 D 6 7 -1
typedef struct { node t[M];
4 E -1 -1 -1 5 F -1 -1 -1 6 G 8 9 10
int length, root ; 7 H -1 -1 -1
} tree;
B ^ C^^^ D ^
E^^^ F^^^ G
H ^^^
I^^^ J^^^ K^^^
要知其然,更要知其所以然。
8/65
树的A存储结构:孩子链表表示法
B CD
EF G
H
IJK
root
data firstChild
0A
1
# define M 50 typedef struct c {
int child; struct c* next; } childNode;
江西师范大学·计算机信息工程学院·计算机科学系
目录
第1章 绪论和预备知识 第2章 线性表 第3章 字符串、数组和特殊矩阵 第4章 递归技术 第5章 树和二叉树 第6章 图 第7章 检索 第8章 内排序
要知其然,更要知其所以然。
2/65
第5章 树和二叉树
树
本章重点
基本概念和术语 逻辑和存储结构 遍历及线性表示
层次遍历:空树返回;否则从根开始从上至下从左至右逐层遍历各个结点。
A
B CD
EF G
H
IJK
前序遍历:ABEFCDGIJKH
后序遍历:EFBCIJKGHDA
层次遍历:ABCDEFGHIJK
关键:类似于以 ab+ 作为公 式书写逆波兰式。
要知其然,更要知其所以然。
11/65
m度树的前序/后序遍历算法
14/65
m度树的层次遍历算法
层次遍历:空树返回;否则从根开始从上至下从左至右逐层遍历各个结点。
算法思想:
levelTravel(tree *t){ if (t==NULL) return;
根入队; while ( 队不空 ) {
initQueue(Q) ; enQueue(Q,t) ; while !empty(Q) {
1、if ( t==NULL) return;
算 法 思
2、输出根; 3、输出左括号;
想 4、按相同方式输出所有子树;
5、输出右括号。
FGHJ I
void kuohao(tree *t){
if (t==NULL) return;
printf( "%c ", t->d );
printf("( ");
for(i=0; i<m; i++){
(C) A
(b) 嵌套 集合 表示 法
A C
B EF
D G
I
HK J
B
凹
E
入
F
表
C
示
D
法
G
遍历操作最重要,查找/输出等可从遍
H
历操作衍生出来。插入/删除等与特定
J
树形有关,不常用。故后续先介绍树
K
的存储结构,之后重点在遍历。
I
要知其然,更要知其所以然。
5/65
树的存储结构:双亲表示法
A
B CD
EF G
} tree;
要知其然,更要知其所以然。
2 3^ 5^ 7^ 9 10^
9/65
树的存储结构:孩子兄弟表示法
A
B CD
EF G
H
IJK
注意:此表示法改变了树的形
状。规律:左孩子,右兄弟。 root
A^
typedef struct k{
B
C^ D ^
char data; struct k *L,*R;
void creaTree ( tree **t ){
int i; tree* t;
int i;
char c=getchar();
char c=getchar();
if (c=='#') return NULL; if (c=='#' ) { *t=NULL; return; }
t= malloc(sizeof(tree)); *t=malloc(sizeof(tree));
3、树中结点的层次(根为1)、树的 深度或高度
JK
4、树枝、路径及其长度
有关树的更多性质参见
5、有序树、无序树、森林 《离散数学》相关内容。
要知其然,更要知其所以然。
4/65
1.2 树的逻辑结构和存储结A构
B
CD
树型结构的逻辑描述
E
F
G HI
JK
a. 括号表示法
A(B(E,F),C,D(G,H(J,K),I))
t->c[i]=creaTree(); return t;
3度树,#代表NULL,建树输入序列为:
ABE###F####C###DGI## #J###K###H####
}
编程:建树,并返回树根和该树中结点数量。
要知其然,更要知其所以然。
13/65
m度树的前序遍历建树算法
tree * creaTree (){
}
要知其然,更要知其所以然。
17/65
树的线性表示:括号表示
假定t由根A和其m棵子树T1,T2,……Tm构成,K(t)是t的括号表示
括号表示规则:
1、空树不表示; 2、若树t只有根,则K(t)=A; ቤተ መጻሕፍቲ ባይዱ、否则, K(t)=A( K(T1) ,K(T2),…, K(Tm) )
A B C DE
FGHJ I
凹
B
入
E
表
F
示
C
法
D
G
H
J
K
I
要知其然,更要知其所以然。
16/65
算法:输出树的凹入表示
B
E
F
A
C
D
G HI
JK
总体采用前序遍历:
算 if ( t==NULL) return; 法 输出根; 思 调整空格和#号数量, 想 按相同方式
输出所有孩子;
void aoruOut(tree * t, int kg, int jh){ int i;//kg:空格数,jh:#数 if (t==NULL) return; /*下面四行输出根*/ for(i=1; i<=kg; i++) printf(" "); printf("%c ",t->d); for(i=1; i<=jh; i++) printf("##"); printf("\n"); for(i=0; i<m; i++)//输出所有孩子 aoruOut(t->c[i], kg+2, jh-2);
t->d=c;
(*t)->d=c;
for (i=0; i<m; i++)
for (i=0; i<m; i++)
t->c[i]=creaTree();
creaTree(&((*t)->c[i]));
return t;
}
} 传回int型值,用int*;传回指针值,用*指针,即二重指针。
要知其然,更要知其所以然。