第4章 树与二叉树
H
I
中序:CEBDFAHGI
(4)
CE B
DFA HG I
例
分别写出右图二叉树的 先序、中序和后序序列。 B
D E F
A
G
AL AR (1) _____________ _____ A C BL BR GL __GA (2) ______ ______ B__ GR CL CR __ DR (3) __ __ C DL __D B H I GA
1、设计算法求二叉树的结点数。
分析: 设置一个全局变量,在遍历二叉树的过程中,对访问的 结点累计计数。 void num( bnode *T ) A //设k是全局变量,初始化k=0 G B { if ( T != NULL ) { k++; C D H num( T -> lchild ); I E F num( T -> rchild ); } }
(4)二叉树子树有序,树无序。
例
比较三个结点的树与二叉树的不同。
三个结点的树:
共两棵
三个结点的二叉树:
共五棵
3、二叉树五种不同的形态:
(1)空树,即结点数为0
(2)单结点二叉树,即仅有一个结点
(3)左子树为空右子树不空 (4)右子树为空左子树不空
(5)左右子树均不空
下图是一棵二叉树:
二、二叉树的性质
顺序存储的一个极端例子:
1
A B
3
2
4
5
6
C
7
1
2
3
4
5
6
7
8
9
10
A
^
B
^
^
^
C
2、动态二叉链表 typedef struct bnode {datatype data; bnode *lchild,*rchild; } 引用:bnode *T
lchild data rchild bnode
空二叉树:T==NULL
2、分析: (1)若T为空,遍历结束;否则转(2) (2) 设二叉树的形态如右图:
L D R
<A>假设左右子树能分别遍历(用 L, R分别表示其遍历),则整个二叉树 可有如下形式的遍历:
先左后右:DLR 先右后左:DRL 先根序 LDR RDL 中根序 LRD RLD 后根序
<B>对于左右子树的遍历,可按照 与整个二叉树相同的方式遍历(递归调用)
36
73
(3)判断题: (√ )完全二叉树中最多有1个度为1的结点。
三、二叉树的存储结构
1、顺序存储方式(不仅要存值,还要存关系)
1
2 4
A
B
E
10 5 6
C
F
3 7
D
9
3
G
8
H
0 1 2 4
I
5 6 7 8 9 10
A
B
C D
E
F G
H
^
I
优点:方便、简洁;
缺点:只适合完全二叉树 或 接近于完全二叉树。
2、设计算法输出二叉树的所有叶子结点的 值。
void leaf( bnode *T) { if ( T != NULL ) { if ( T -> lchild == NULL && T -> rchild == NULL ) cout<<T->data; leaf( T -> lchild ); A leaf( T -> rchild ); } G B }
如下图的二叉树:
T A B C D G E F F ^ ^ C ^ ^ D ^ B A ^ E
n个结点的二叉链表共有2n个指针域。 ^ G ^ 其中n-1个不空,剩下2n-(n-1)=n+1个指针域为空。
§4.3 二叉树的遍历
一、二叉树遍历算法的实现
1、遍历:按照某种次序依次访问二叉树T中 每个结点一次且仅一次。
后序遍历二叉树T 若T不空,则: 后序访问其左子树; 后序访问其右子树; 访问根。
void postorder(bnode *t) { if(t!=NULL) { postorder(t->lchild); postorder(t->rchlid); visit(t->data); } }
二、遍历的应用
void preorder(bnode *t) { if(t!=NULL) { visit(t->data); preorder(t->lchild); preorder(t->rchlid); } }
中序遍历二叉树T 若T不空,则: 中序访问其左子树; 访问根; 中序访问其右子树。
void inorder(bnode *t) { if(t!=NULL) { inorder(t->lchild); visit(t->data); inorder(t->rchlid); } }
一、线索二叉树结构
1、定义:
线索:将空的左孩子指针改为指向前驱;
将空的右孩子指针改为指向后继; 修改过的指针称为线索。
修改的过程称为线索化;
为能区分孩子指针和线索需要增设标志: ltag= 0 lchild指向左孩子; = 1 lchild指向前驱; rtag= 0 rchild指向右孩子; = 1 rchild指向后继。
2、线索二叉树:
先序线索二叉树
A
中序线索二叉树
A
B
C E D F H
G
I
B
G
C
E
D
F
H
I
将空的左孩子指针改为指向前驱; 将空的右孩子指针改为指向后继;
课堂练习:后序线索二叉树
后序线索二叉树
A B C E D F H G
I
将空的左孩子指针改为指向前驱; 将空的右孩子指针改为指向后继;
思考
先序线索二叉树最后一个结点的后继线索 有什么特点?
算法与数据结构
阙夏制作
§4
树和二叉树
树形结构是一类很重要的非线性结构。 结构中,元素有明显的分支和层次关系。 树形结构在客观世界广泛存在,如家族关 系的家谱、各种社会组织机构、书的章节 划分等等。
树形结构如下图:
A11
A21
A22
A31
A32
A33
A34
A35
§ 4.1
树的定义
一、树的定义和有关术语
3、有关遍历方法的例题:
例
分别写出右图二叉树的 先序、中序和后序序列。 B
D F
A
G
C AR AL (1) A ______________ _______
BL BR G GR (2) AB ______ ______ G __L __ E C C DL DR (3) ABC__ L__R D __ __ G H I
1、定义:
树 是n个结点(n>0)的有限集合。
仅有一个根结点; 其它结点可划分为m(m ≥ 0)个互不相交 的子集,每个子集也构成树——子树。
2、有关术语
关系术语: 父结点 孩子结点 兄弟结点
祖先、后代
A11
A21
A22
A31
A32
A33
A34
A35
层次类术语 层次:根的层次为1 其余结点的层次=其父结点层次+1
§4.4 线索二叉树
问题:对给定次序(先、中、后序)求某结点 的前驱或后继(二叉链表)。 求解方法 (1)遍历——费时; (2)给每个结点增设前驱后继指针; (3)利用二叉链表中n+1个空指针;
下图为一个二叉链表:
T A B E B A ^ E F ^ G ^ C ^ ^ D ^
C
D
F
n个结点的二叉链表共有2n个指针域。 ^ G ^ 其中n-1个不空,剩下2n-(n-1)=n+1个指针域为空。
A
解
A
CDBE GF
B
A C B CD E G F D E G
F
课堂练习
已知一棵二叉树的后序序列和中序序列, 要求还原该二叉树。 中序:CBEDAFG 后序:CEDBGFA
A
A A
B
FG C B ED F G C E D
F
G
CBED
思考:只有先序和后序能否唯一还原二叉树?
4、遍历算法 先序遍历二叉树T 若T不空,则: 访问根; 先序访问其左子树; 先序访问其右子树。
(n=0为空二叉树)
仅有一个根结点;
其余结点可划分为两个互不相交的子集, 且这两个子集也构成二叉树——左右子 树。
二叉树大多用图的形式表示,如下图:
下图也是一棵二叉树:
2、二叉树与树的区别:
(1)是两种不同的结构;
(2)二叉树有空的概念,而树没有;
(3)二叉树恰有两棵子树,树可有0到多棵;
B11
A11
A21
A22
A31
A32
A33
A34
A35
B21
二、 树的运算
运算 (1)初始化; (2)查找 — 结点的父、兄弟、祖先、 后代、根; (3)插入 — 叶子,子树; (4)删除 — 叶子,子树。
树的存储?
§ 4.2 二叉树的定义和性质
一、二叉树的基本概念
1、定义
二叉树 是n个(n≥0)结点的有限集合。
(1)求100个结点的完全二叉树的叶子结点数。
解
1
50
100
根据性质5,从编号51到100都是叶子。 共有50个叶子。
(2)完全二叉树的第7层有10个结点,问共有几个 结点?多少个叶子结点?多少个度为1的结点?