数据结构讲义(严蔚敏版)第六章 树和二叉树
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2i-1 … … 2i-1
2层:21 … i层:2i-1 …
2k-1
2k-1 k层:2k-1
满二叉树和完全二叉树
满二叉树:一棵深度为k且有2k-1个结点的二叉树。 完全二叉树:若深度为k、有n个结点的二叉树中各结
点能与深度为k的顺序编号的满二叉树编号从1到n的结 点相对应。
所有的叶结点都出现在第k层或k-1层。 若任一结点右子树最大层次为l,其左子树最大层
{ if(visit(T->data))//访问当前的根结点 if(PreorderTraverse(T->lchild,visit))//先序遍历左子树 if(PreorderTraverse(T->rchild,visit))//先序遍历右子树 return OK;
return ERROR;//若访问不到当前根结点值,出错 } else return OK;//树空 } 时间复杂度:n个结点的二叉树先序遍历时间复杂度O(n)
} ADT Tree
6.1树的定义和基本术语(续)
结点的度:分支的个数 树的度:树中所有结点的度的最大值 树的深度(高度):树中叶子结点所在的最大层次
6.1树的定义和基本术语(续)
双亲(结点): 孩子(结点):结点子树的根称为该结点的孩子 祖先(结点) :从根到该结点所经分支上的所有结点。 子孙(结点) :以某结点为根的子树的任一结点 兄弟(结点) :同一双亲的孩子互称兄弟。 堂兄弟(结点) :双亲在同一层的结点互称堂兄弟
typedef struct BiTNode {
TElemType data; struct BiTNode *lchild,*rchild;
lChild rChild
} BiTNode,*BiTree;
三叉链表: 二叉树的三叉链表C语言描述
typedef struct ThiTNode {
lChild data parent rChild parent
} ADT BinaryTree
6.2.2 二叉树的性质
性质1:在二叉树的第i层上至多有2i-1个结点(i>=1)。
性质2:深度为k的二叉树至多有2k-1个结点(k>=1).
性质3:对任一棵二叉树,若其终端结点数为n0,度为 2的结点数为n2,则n0=n2+1。
1
1层:20
23
…………………
6.1树的定义和基本术语
树:n(n≥0)个结点的有限集。在任一棵非空树中: 1.有且仅有一个特定称为根的结点 2.n>1时,其余结点可分为m(m>0)个互不相交的 有限集T1,T2,…,Tn,Ti称为树的子树。
树的性质: 递归性 层次性
基本术语: 树的结点:数据元素及若干指向其子树的分支 叶子(终端结点):度(分支的个数)为零的结点 分支结点(非终端结点):度大于零的结点
KL
M
6、结点K的双亲是 。
7、结点F的堂兄弟是 。
树的表示法
A
E
A
BF
G
H J
C
K
ID
A
(a)嵌套集合表示法
BCD
E FGHJ I
KL
M
(d)树形表示法
B E F
C G
D H I K J
(b)凹入表示法
(A(B(E,F),C(G),D(H,J,I(K)))) (c)广义表表示法
6.2 二叉树
学习二叉树的目的 二叉树存储结构和基本操作实现简单
二叉树中序遍历递归算法改非递归算法(1)
void InorderTraverse(BiTree T,int (*visit)(char e)) { if(T)//树不空
{ InorderTraverse(T->lchild,visit);//中序遍历左子树 visit(T->data);//访问根结点 InorderTraverse(T->rchild,visit);//中序遍历右子树
遍历二叉树有DLR、LDR、LRD、DRL、RDL、 RLD六种方案。若规定先左后右,则只有三种:
DLR—先(根)序遍历,
D
LDR—中(根)序遍历,
LRD—后(根)序遍历。
6.3.1遍历二叉树
先序遍历
访问根结点;
A
先序遍历左子树;
先序遍历右子树;
中序遍历
中序遍历左子树; 访问根结点; 中序遍历右子树;
难点:
二叉树的二叉链表存储结构及其上的各种遍历算法实现
线性结构和树形结构的对比
1
春夏 秋 冬
2
3
456
第一个元素
最后一个元 素
其它数据元 素
线性结构
树结构
第一个数据元素
根结点
(无前驱)
(无前驱)
最后一个数据元 素(无后继)
多个叶子结点 (无后继)
一个直接前驱和
树中其它结点
一个直接后继 (一个直接前驱、多个直接后继)
任何树都可与二叉树相互转换,解决了树的存储结 构及运算复杂性的问题。
二叉树递归定义:由n(n>=0)个结点的有限集合,或 为空集,或由一个根结点及两棵互不相交的左右子树 组成,并且左右子树都是二叉树。
二叉树的五种不同形态
二叉树的抽象数据类型定义
ADT BinaryTree { 数据对象 D: D是具有相同特性的元素集合 数据关系R: 若D为空集, 则称空树;若D中只含一个数据元素,则R为空集,否 则R={H},H是如下二元关系: (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; (2)若D-{root}非空,则存在一个划分Dl,Dr, 且Dl Dr=, (HH3)中r若在;DH若l中≠Dr;≠,H则=,D则{<l存rDor在o存t,数x在l>据数,<元据ro素o元tx,素xlr>x,DrHl,l,D有Hrr,<}有;ro<ort,oxolt,>xr >H;且H存;且在存D在l上D关r上系关H系l在 (一3)棵(D符i,{合Hl本} )定是义一的棵二符叉合树本,定称义为的根二的叉右树子,树称。为根的左子树; (Dr,{Hr} )是 基本操作:InitBiTree(&T); DestroyBiTree(&T); CreateBiTree(&T,definition); ClearBiTree(&T); BiTreeEmpty(T); BiTreeDepth(T); Root(T); Value(T,e); Assign(T,&e, value); Parent(T, e); LeftChild(T, e); RightSibling(T, e); InsertChild(&T,p,LR,c); DeleteChild(&T,p,LR); PreOrderTraverse (T,visit()); InOrderTraverse (T,visit()); PostOrderTraverse (T,visit()); LevelOrderTraverse (T,visit());
有序树:树中结点的各子树从左到右有次序(不能互 换)。
无序树:树中结点的各子树从左到右无次序(能互换)。 森林:m(m≥0)棵互不相交的树的集合
6.1树的定义和基本术语(续)
举例:如图的树,回答以下问题: 1、树的根是 。
A
2、树的叶子是 。
BCD E FGHJ I
3、结点D的度是 。 4、结点B的孩子是 , 子孙 。 5、树的度是 ,深度是 。
}
}
将算法中第二个递归语句消去, 用循环实现 void InorderTraverse(BiTree T,int (*visit)(char e)) { if(T)//树不空
{ InorderTraverse(T->lchild,visit);//中序遍历左子树 visit(T->data);//访问根结点 T = T→rchild;
#define MAX_TREE_SIZE 100 typedef TElemType SqBiTree[MAX_TREE_SIZE]; SqBiTree bt;
6.2.3 二叉树的存储结构(2)
链式存储结构 二叉链表:
lChild data rChild
二叉树的二叉链表C语言描述
data
第六章 树和二叉树
非线性结构
第六章 树和二叉树
树是以分支关系定义的层次结构
树的定义、相关术语、存储结构 二叉树的定义、五个重要性质和存储结构 二叉树的遍历、线索化操作 树和森林与二叉树的转换 二叉树的应用-huffman编码和译码
重点:
1. 二叉树的性质及遍历算法 2. 理解二叉树的线索化过程 3. 掌握树和森林与二叉树的转换关系
(1)若i=1,i无双亲,是二叉树的根;若i>1,其双亲是结点i/2
(2)若2i>n,i为叶子结点,无左孩子;否则,其左孩子是结点2i。
(3)若2i+1>n,则i无右孩子;否则,其右孩子是结点2i+1。
1
i/2
…… i
23 ……
i
i+1
i+1 … 2i
2i+1
i i+1 i+2 i+3 2i 完全二叉树
TElemType data;
data
struct ThiTNode *lchild,*rchild,*parent;
} ThiTNode,*ThiTree;
lChild
rChild
二叉树的链式存储结构示例
T
T
A
A^
A ^^
B CD
B ^ C^ D
B ^C ^ D
EF G
^E
^F^
^ G^
^E
^F ^
树的抽象数据类型定义
ADT Tree { 数据对象 D: D是具有相同特性的元素集合 数据关系R: 若D为空集, 则称空树;若D中只含一个数据元素,则R为空集,否则 R={H},H是如下二元关系: (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; (2)若D-{root}非空,则存在一个划分D1,D2,…,Dm(m>0),对任意jk(1j,k m)有Dj Dk=,且对任意的i (1i m),惟一存在数据元素xi Di, 有<root, xi > H; (3分) 对H1应,H于2,…D,-H{rmo(omt}>的0)划, 对分任,意H-jk{(1<jr,okot,mx)1有> H,j… ,H<kr=oot,,且xm对>任}意有的惟i (一1的i 一m个),划 Hj是Di上的二元关系,( Di ,{ Hi })是一棵符合本定义的树,称为根root的子树。 基本操作:InitTree(&T); DestroyTree(&T); CreateTree(&T,definition); ClearTree(&T); TreeEmpty(T); TreeDepth(T); Root(T); Value(T,cur_e); Assign(T, cur_e, value); Parent(T, cur_e); LeftChild(T,cur_e); RightSibling(T,cur_e); InsertChild(&T,&p,i,c); DeleteChild(&T,&p,i); TraverseTree(T,visit());
B CD
先序序列:ABCDEGF
中序序列:CBEGDFA 后序序列:CGEFDBA 层序序列:ABCDEFG
后序遍历
后序遍历左子树;
EF
后序遍历右子树;
G
访问根结点
层序遍历
按从上到下,从左到右的顺序访问结点
先序遍历的递归算法
Status PreorderTraverse(BiTree T,int (*visit)(char e)) { if(T)//树不空
^G ^
二叉树T
T的二叉链表
T的三叉链表
6.3 遍历二叉树和线索二叉树
遍历二叉树:按某条搜索路径巡访树中的每一个结点, 使每一个结点均被访问一次且仅被访问一次。
在树中查找具有某种特征的结点;
对树中全部结点逐一进行某种处理;
寻找遍历二叉树的规律
二叉树基本组成:根结点D、左子树L和右子树R。
2i 2i+1 2i+2 2i+3 2i+2 2i+3
i和i+1结点在同一层
i和i+1结点不在同一层
6.2.3 二叉树的存储结构(1)
顺序存储结构:用一组地址连续的存储单元依次自上而下、 自左至右存储二叉树的结点。仅适用于完全二叉树。
缺点:可能对存储空间造成极大的浪费,比如单支树。 二叉树的顺序存储表示的C语言描述:
次为1或l+1。
1
1
1
1
23Βιβλιοθήκη 2323
2
3
4 56 7 4
45
6
45
(a)满二叉树 (b)完全二叉树 (c)非完全二叉树 (d)非完全二叉树
性质4:有n个结点的完全二叉树的深度为log2n +1。
6.2.2 二叉树的性质
性质5: 若对一棵有n个结点的完全二叉树结点按层序编号(从 第有1:层到第log2n +1层,每层从左到右),对任一结点i(1≤i≤n),
2层:21 … i层:2i-1 …
2k-1
2k-1 k层:2k-1
满二叉树和完全二叉树
满二叉树:一棵深度为k且有2k-1个结点的二叉树。 完全二叉树:若深度为k、有n个结点的二叉树中各结
点能与深度为k的顺序编号的满二叉树编号从1到n的结 点相对应。
所有的叶结点都出现在第k层或k-1层。 若任一结点右子树最大层次为l,其左子树最大层
{ if(visit(T->data))//访问当前的根结点 if(PreorderTraverse(T->lchild,visit))//先序遍历左子树 if(PreorderTraverse(T->rchild,visit))//先序遍历右子树 return OK;
return ERROR;//若访问不到当前根结点值,出错 } else return OK;//树空 } 时间复杂度:n个结点的二叉树先序遍历时间复杂度O(n)
} ADT Tree
6.1树的定义和基本术语(续)
结点的度:分支的个数 树的度:树中所有结点的度的最大值 树的深度(高度):树中叶子结点所在的最大层次
6.1树的定义和基本术语(续)
双亲(结点): 孩子(结点):结点子树的根称为该结点的孩子 祖先(结点) :从根到该结点所经分支上的所有结点。 子孙(结点) :以某结点为根的子树的任一结点 兄弟(结点) :同一双亲的孩子互称兄弟。 堂兄弟(结点) :双亲在同一层的结点互称堂兄弟
typedef struct BiTNode {
TElemType data; struct BiTNode *lchild,*rchild;
lChild rChild
} BiTNode,*BiTree;
三叉链表: 二叉树的三叉链表C语言描述
typedef struct ThiTNode {
lChild data parent rChild parent
} ADT BinaryTree
6.2.2 二叉树的性质
性质1:在二叉树的第i层上至多有2i-1个结点(i>=1)。
性质2:深度为k的二叉树至多有2k-1个结点(k>=1).
性质3:对任一棵二叉树,若其终端结点数为n0,度为 2的结点数为n2,则n0=n2+1。
1
1层:20
23
…………………
6.1树的定义和基本术语
树:n(n≥0)个结点的有限集。在任一棵非空树中: 1.有且仅有一个特定称为根的结点 2.n>1时,其余结点可分为m(m>0)个互不相交的 有限集T1,T2,…,Tn,Ti称为树的子树。
树的性质: 递归性 层次性
基本术语: 树的结点:数据元素及若干指向其子树的分支 叶子(终端结点):度(分支的个数)为零的结点 分支结点(非终端结点):度大于零的结点
KL
M
6、结点K的双亲是 。
7、结点F的堂兄弟是 。
树的表示法
A
E
A
BF
G
H J
C
K
ID
A
(a)嵌套集合表示法
BCD
E FGHJ I
KL
M
(d)树形表示法
B E F
C G
D H I K J
(b)凹入表示法
(A(B(E,F),C(G),D(H,J,I(K)))) (c)广义表表示法
6.2 二叉树
学习二叉树的目的 二叉树存储结构和基本操作实现简单
二叉树中序遍历递归算法改非递归算法(1)
void InorderTraverse(BiTree T,int (*visit)(char e)) { if(T)//树不空
{ InorderTraverse(T->lchild,visit);//中序遍历左子树 visit(T->data);//访问根结点 InorderTraverse(T->rchild,visit);//中序遍历右子树
遍历二叉树有DLR、LDR、LRD、DRL、RDL、 RLD六种方案。若规定先左后右,则只有三种:
DLR—先(根)序遍历,
D
LDR—中(根)序遍历,
LRD—后(根)序遍历。
6.3.1遍历二叉树
先序遍历
访问根结点;
A
先序遍历左子树;
先序遍历右子树;
中序遍历
中序遍历左子树; 访问根结点; 中序遍历右子树;
难点:
二叉树的二叉链表存储结构及其上的各种遍历算法实现
线性结构和树形结构的对比
1
春夏 秋 冬
2
3
456
第一个元素
最后一个元 素
其它数据元 素
线性结构
树结构
第一个数据元素
根结点
(无前驱)
(无前驱)
最后一个数据元 素(无后继)
多个叶子结点 (无后继)
一个直接前驱和
树中其它结点
一个直接后继 (一个直接前驱、多个直接后继)
任何树都可与二叉树相互转换,解决了树的存储结 构及运算复杂性的问题。
二叉树递归定义:由n(n>=0)个结点的有限集合,或 为空集,或由一个根结点及两棵互不相交的左右子树 组成,并且左右子树都是二叉树。
二叉树的五种不同形态
二叉树的抽象数据类型定义
ADT BinaryTree { 数据对象 D: D是具有相同特性的元素集合 数据关系R: 若D为空集, 则称空树;若D中只含一个数据元素,则R为空集,否 则R={H},H是如下二元关系: (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; (2)若D-{root}非空,则存在一个划分Dl,Dr, 且Dl Dr=, (HH3)中r若在;DH若l中≠Dr;≠,H则=,D则{<l存rDor在o存t,数x在l>据数,<元据ro素o元tx,素xlr>x,DrHl,l,D有Hrr,<}有;ro<ort,oxolt,>xr >H;且H存;且在存D在l上D关r上系关H系l在 (一3)棵(D符i,{合Hl本} )定是义一的棵二符叉合树本,定称义为的根二的叉右树子,树称。为根的左子树; (Dr,{Hr} )是 基本操作:InitBiTree(&T); DestroyBiTree(&T); CreateBiTree(&T,definition); ClearBiTree(&T); BiTreeEmpty(T); BiTreeDepth(T); Root(T); Value(T,e); Assign(T,&e, value); Parent(T, e); LeftChild(T, e); RightSibling(T, e); InsertChild(&T,p,LR,c); DeleteChild(&T,p,LR); PreOrderTraverse (T,visit()); InOrderTraverse (T,visit()); PostOrderTraverse (T,visit()); LevelOrderTraverse (T,visit());
有序树:树中结点的各子树从左到右有次序(不能互 换)。
无序树:树中结点的各子树从左到右无次序(能互换)。 森林:m(m≥0)棵互不相交的树的集合
6.1树的定义和基本术语(续)
举例:如图的树,回答以下问题: 1、树的根是 。
A
2、树的叶子是 。
BCD E FGHJ I
3、结点D的度是 。 4、结点B的孩子是 , 子孙 。 5、树的度是 ,深度是 。
}
}
将算法中第二个递归语句消去, 用循环实现 void InorderTraverse(BiTree T,int (*visit)(char e)) { if(T)//树不空
{ InorderTraverse(T->lchild,visit);//中序遍历左子树 visit(T->data);//访问根结点 T = T→rchild;
#define MAX_TREE_SIZE 100 typedef TElemType SqBiTree[MAX_TREE_SIZE]; SqBiTree bt;
6.2.3 二叉树的存储结构(2)
链式存储结构 二叉链表:
lChild data rChild
二叉树的二叉链表C语言描述
data
第六章 树和二叉树
非线性结构
第六章 树和二叉树
树是以分支关系定义的层次结构
树的定义、相关术语、存储结构 二叉树的定义、五个重要性质和存储结构 二叉树的遍历、线索化操作 树和森林与二叉树的转换 二叉树的应用-huffman编码和译码
重点:
1. 二叉树的性质及遍历算法 2. 理解二叉树的线索化过程 3. 掌握树和森林与二叉树的转换关系
(1)若i=1,i无双亲,是二叉树的根;若i>1,其双亲是结点i/2
(2)若2i>n,i为叶子结点,无左孩子;否则,其左孩子是结点2i。
(3)若2i+1>n,则i无右孩子;否则,其右孩子是结点2i+1。
1
i/2
…… i
23 ……
i
i+1
i+1 … 2i
2i+1
i i+1 i+2 i+3 2i 完全二叉树
TElemType data;
data
struct ThiTNode *lchild,*rchild,*parent;
} ThiTNode,*ThiTree;
lChild
rChild
二叉树的链式存储结构示例
T
T
A
A^
A ^^
B CD
B ^ C^ D
B ^C ^ D
EF G
^E
^F^
^ G^
^E
^F ^
树的抽象数据类型定义
ADT Tree { 数据对象 D: D是具有相同特性的元素集合 数据关系R: 若D为空集, 则称空树;若D中只含一个数据元素,则R为空集,否则 R={H},H是如下二元关系: (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; (2)若D-{root}非空,则存在一个划分D1,D2,…,Dm(m>0),对任意jk(1j,k m)有Dj Dk=,且对任意的i (1i m),惟一存在数据元素xi Di, 有<root, xi > H; (3分) 对H1应,H于2,…D,-H{rmo(omt}>的0)划, 对分任,意H-jk{(1<jr,okot,mx)1有> H,j… ,H<kr=oot,,且xm对>任}意有的惟i (一1的i 一m个),划 Hj是Di上的二元关系,( Di ,{ Hi })是一棵符合本定义的树,称为根root的子树。 基本操作:InitTree(&T); DestroyTree(&T); CreateTree(&T,definition); ClearTree(&T); TreeEmpty(T); TreeDepth(T); Root(T); Value(T,cur_e); Assign(T, cur_e, value); Parent(T, cur_e); LeftChild(T,cur_e); RightSibling(T,cur_e); InsertChild(&T,&p,i,c); DeleteChild(&T,&p,i); TraverseTree(T,visit());
B CD
先序序列:ABCDEGF
中序序列:CBEGDFA 后序序列:CGEFDBA 层序序列:ABCDEFG
后序遍历
后序遍历左子树;
EF
后序遍历右子树;
G
访问根结点
层序遍历
按从上到下,从左到右的顺序访问结点
先序遍历的递归算法
Status PreorderTraverse(BiTree T,int (*visit)(char e)) { if(T)//树不空
^G ^
二叉树T
T的二叉链表
T的三叉链表
6.3 遍历二叉树和线索二叉树
遍历二叉树:按某条搜索路径巡访树中的每一个结点, 使每一个结点均被访问一次且仅被访问一次。
在树中查找具有某种特征的结点;
对树中全部结点逐一进行某种处理;
寻找遍历二叉树的规律
二叉树基本组成:根结点D、左子树L和右子树R。
2i 2i+1 2i+2 2i+3 2i+2 2i+3
i和i+1结点在同一层
i和i+1结点不在同一层
6.2.3 二叉树的存储结构(1)
顺序存储结构:用一组地址连续的存储单元依次自上而下、 自左至右存储二叉树的结点。仅适用于完全二叉树。
缺点:可能对存储空间造成极大的浪费,比如单支树。 二叉树的顺序存储表示的C语言描述:
次为1或l+1。
1
1
1
1
23Βιβλιοθήκη 2323
2
3
4 56 7 4
45
6
45
(a)满二叉树 (b)完全二叉树 (c)非完全二叉树 (d)非完全二叉树
性质4:有n个结点的完全二叉树的深度为log2n +1。
6.2.2 二叉树的性质
性质5: 若对一棵有n个结点的完全二叉树结点按层序编号(从 第有1:层到第log2n +1层,每层从左到右),对任一结点i(1≤i≤n),