第4章 树与二叉树

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1
i / 2
3
2
i
4 5 6 7 13
8
9
10
11
12
2i
2i+1
课堂练习
(1)求100个结点的完全二叉树的叶子结点数。

a) 有7层; b) 前6层共26-1=63个结点; 第7层有100-63=37个; 第6层有26-1=32个结点; c) 第6层19个非叶子结点; 有32-19=13个叶子结点; 所以共有37+13=50个叶子结点。
算法与数据结构
阙夏制作
§4
树和二叉树
树形结构是一类很重要的非线性结构。 结构中,元素有明显的分支和层次关系。 树形结构在客观世界广泛存在,如家族关 系的家谱、各种社会组织机构、书的章节 划分等等。
树形结构如下图:
A11
A21
A22
A31
A32
A33
A34
A35
§ 4.1
树的定义
一、树的定义和有关术语
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
课堂练习
已知一棵二叉树中,有20个叶子结点,10个 结点只有左孩子,15个结点只有右孩子,求 该二叉树的总结点数。 解: n=n0+n1+n2 n0=20 n2=n0-1=19(性质3) n1=15+10=25 n=20+19+25=64

定义1:高度为k且有2k-1个结点的二叉树为满二
叉树;
如下图:

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)二叉树子树有序,树无序。

比较三个结点的树与二叉树的不同。
三个结点的树:
共两棵
三个结点的二叉树:
共五棵
3、二叉树五种不同的形态:
(1)空树,即结点数为0
(2)单结点二叉树,即仅有一个结点
(3)左子树为空右子树不空 (4)右子树为空左子树不空
(5)左右子树均不空
下图是一棵二叉树:
二、二叉树的性质
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 }
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
优点:方便、简洁;
缺点:只适合完全二叉树 或 接近于完全二叉树。
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); } }

高度(深度):整个树中结点的最大层次;
A11
A21
A22
A31
A32
A33
A34
A35

度:孩子结点的数目。
叶子(终结点)——度为0; 分支结点(非叶子结点)
——度不为0的结点;
树的度——最大的结点度;
A11
A21
A22
A31
A32
A33
A34
A35

森林: 多棵树; 有序树/无序树:
树中各兄弟结点之间的排列是否有序。
1、定义:
树 是n个结点(n>0)的有限集合。

仅有一个根结点; 其它结点可划分为m(m ≥ 0)个互不相交 的子集,每个子集也构成树——子树。
2、有关术语

关系术语: 父结点 孩子结点 兄弟结点
祖先、后代
A11
A21
A22
A31
A32
A33
A34
A35
层次类术语 层次:根的层次为1 其余结点的层次=其父结点层次+1
顺序存储的一个极端例子:
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
B11
A11
A21
A22
A31
A32
A33
A34
A35
B21
二、 树的运算
运算 (1)初始化; (2)查找 — 结点的父、兄弟、祖先、 后代、根; (3)插入 — 叶子,子树; (4)删除 — 叶子,子树。

树的存储?
§ 4.2 二叉树的定义和性质
一、二叉树的基本概念
1、定义
二叉树 是n个(n≥0)结点的有限集合。
C E D F I H
3、求给定二叉树的高度:
A B G
C D H 分析: I (1)t==NULL——高度为0; E F (2)否则,设左子树高度为hl,右子树高度为hr, 则二叉树高度h为max(hl,hr)+1; (3)左右子树的高度可以通过递归形式求出。
int high(bnode *t) { if(t==NULL) return(0); else return(max(high(t->lchild),h来自百度文库gh(t->rchild))+1); }
如下图的二叉树:
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中 每个结点一次且仅一次。
一、线索二叉树结构
1、定义:

线索:将空的左孩子指针改为指向前驱;
将空的右孩子指针改为指向后继; 修改过的指针称为线索。

修改的过程称为线索化;
为能区分孩子指针和线索需要增设标志: ltag= 0 lchild指向左孩子; = 1 lchild指向前驱; rtag= 0 rchild指向右孩子; = 1 rchild指向后继。
后序遍历二叉树T 若T不空,则: 后序访问其左子树; 后序访问其右子树; 访问根。
void postorder(bnode *t) { if(t!=NULL) { postorder(t->lchild); postorder(t->rchlid); visit(t->data); } }
二、遍历的应用
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
H
I
先序:ABCEDFGHI
(4) ABC
E D
F G H I

分别写出右图二叉树的 先序、中序和后序序列。 B
C E D F
A
G
AL AR (1) _____________A______
BL BR G G (2) _____ B _____ A __L G __R CL CR DL DR (3) __C__ B__D__ A H G I
2、分析: (1)若T为空,遍历结束;否则转(2) (2) 设二叉树的形态如右图:
L D R
<A>假设左右子树能分别遍历(用 L, R分别表示其遍历),则整个二叉树 可有如下形式的遍历:
先左后右:DLR 先右后左:DRL 先根序 LDR RDL 中根序 LRD RLD 后根序
<B>对于左右子树的遍历,可按照 与整个二叉树相同的方式遍历(递归调用)
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不空,则: 访问根; 先序访问其左子树; 先序访问其右子树。
§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个指针域为空。
H
I
后序:ECFDBHIGA
(4)
E C
F D B H I GA
课堂练习

分别写出下图二叉树的先、中、后序。
A
B C E D F G H
先序:ABCDEFGHI 中序:CBEDFAGIH 后序:CEFDBIHGA
I

已知一棵二叉树的先序序列和中序序列, 要求还原该二叉树。 先序:ABCDEFG 中序:CDBEAGF
性质1:在二叉树的第i层上的结点数≤2i-1 (i>0)。 性质2:高度为k的二叉树的结点数≤2k-1 (k>0)。
第1层 1=20 第2层 1×2=21





第i层 2i-1
20+21+22+…+2k-1=2k-1
性质3:对任一棵非空的二叉树T,如果其叶子 数为n0,度为2的结点数为n2,则有下面的关 系式成立:n0=n2+1。 证明:设T的总结点数为n,度为1的结点数为n1, 则T的结点数满足下面关系式: n=n0+n1+n2 (a) n-1=n1+2n2 (b) 综合(a)和(b)两式得:n0=n2+1。 得证。
(1)求100个结点的完全二叉树的叶子结点数。

1
50
100
根据性质5,从编号51到100都是叶子。 共有50个叶子。
(2)完全二叉树的第7层有10个结点,问共有几个 结点?多少个叶子结点?多少个度为1的结点?

a)共有26-1+10=73个结点; b)37到73都是叶子,共37个叶子结点;
1
c)度为1的结点数为0。
定义2:在满二叉树最下一层从右到左依次连续 去掉若干个结点的二叉树称为完全二叉树。 如下图:
下图不是一棵完全二叉树:
性质4:有n个(n≥1)结点的完全二叉树的高 度为 log 2 n + 1 。
高度为k的满二叉树有2k-1个结点;
性质5:对完全二叉树进行层次编号,编号为i 的结点,其左孩子的编号为2i,右孩子编号 为2i+1,其父结点的编号为:i / 2 。
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 ); } }
中序线索二叉树第一个结点的前驱线索有 什么特点,最后一个结点的后继线索有什 么特点? 后序线索二叉树第一个结点的前驱线索有 什么特点?


构造二叉树

输入数据 => 构造算法
(n=0为空二叉树)


仅有一个根结点;
其余结点可划分为两个互不相交的子集, 且这两个子集也构成二叉树——左右子 树。
二叉树大多用图的形式表示,如下图:
下图也是一棵二叉树:
2、二叉树与树的区别:
(1)是两种不同的结构;
(2)二叉树有空的概念,而树没有;
(3)二叉树恰有两棵子树,树可有0到多棵;
相关文档
最新文档