1.73k likes | 1.86k Views
第六章 树 (Tree) 和二叉树 (Binary Tree). 树的定义和基本术语 二叉树 遍历二叉树和线索二叉树 树和森林 赫夫曼树及其应用. ……. ……. 示例. 计算机与人对弈问题. 示例. 以树结构描述测试假币的称重策略. A. B. C. D. E. F. G. H. I. J. 示例. 一个家族 : A 有子女 B, C ; B 和 C 分别有子女 D, E, F 和 G, H ; E 有子女 I , J 。. 6.1 树的定义和基本术语. 树 是一类重要的 非线性 数据结构,是 以分支关系定义的层次结构 。
E N D
第六章 树(Tree)和二叉树(Binary Tree) 树的定义和基本术语 二叉树 遍历二叉树和线索二叉树 树和森林 赫夫曼树及其应用
…… …… 示例 计算机与人对弈问题
示例 以树结构描述测试假币的称重策略
A B C D E F G H I J 示例 一个家族: • A有子女B, C;B和C分别有子女D, E, F和G, H;E有子女I , J。
6.1 树的定义和基本术语 • 树是一类重要的非线性数据结构,是以分支关系定义的层次结构。 • 由于树形结构中的各子结构与整个结构具有相似的特性,因而其算法大多采用递归形式,
树是由 n (n 0) 个结点组成的有限集合。 如果n = 0,称为空树; 如果n > 0,则 有一个特定的称之为根(root)的结点,它只有直接后继,但没有直接前驱; 除根以外的其它结点划分为 m (m 0) 个互不相交的有限集合T1, T2, …, Tm,每个集合又是一棵树,并且称之为根的子树(Subtree) 。 • 任何一棵树是一个二元组Tree=(root,F), 其中root称为树的根结点,F是m(m0)棵子树构成的森林,F=(T1, T2,…,Tm),其中Ti=(ri, Fi)称作根root的第i 棵子树;当m0时,在树根和其子树森林之间存在下列关系: RF={<root, ri> | i=1, 2, …, m, m>0} 树的递归定义
只有根结点的树 有子树的树 A A B C D E F G H I J K L M 根 子树
A B C D E F G H I J 树的表示 • 树型表示:
A a b d B C e i D E F G H j f c I J g h 树的表示 • 凹入表表示:
A B C A B E C D E F D I J F G G H H I J 树的表示 • 嵌套集合表示:
A B C D E F G H I J 树的表示 • 嵌套括号表示: A ( B( D, E ( I, J ), F ), C( G, H ))
基本术语 • 结点(node)——表示树中的元素,包括数据项及若干指向 其子树的分支 • 结点的度(degree)——结点拥有的子树数 • 叶子(leaf)或终端结点——度为0的结点 • 孩子(child)——结点的子树的根 • 双亲(parents)——孩子结点的上层结点 • 兄弟(sibling)——同一双亲的孩子 • 树的度(degree)——一棵树中最大的结点度数 • 结点的层次(level)——从根结点算起,根为第一层,它 的孩子为第二层…… • 深度(depth)或高度(height)——树中结点的最大层次数 • 森林(forest)——m(m0)棵互不相交的树的集合
其他基本术语 • 分支结点或非终端结点——度不为0的结点 • 祖先——从根到该结点所经分支上的所有结点 • 子孙——以该结点为根的子树中的所有结点 • 堂兄弟——双亲在同一层的结点互为堂兄弟 • 有序树——树中结点的各子树从左至右有次序 • 无序树——树中结点的各子树从左至右无次序
A B C D E F G H I J K L M 结点A的孩子:B,C,D 结点B的子孙:E,F,K,L 叶子或终端结点: K,L,F,G,M,I,J 结点I的双亲:D 结点L的双亲:E 结点A的度:3 结点B的度:2 结点M的度:0 结点B,C,D为兄弟 结点K,L为兄弟 树的度:3 结点F,G为堂兄弟 结点A、B是结点F的祖先 结点A的层次:1 结点M的层次:4 树的深度:4
树的基本操作 • 构造一个树 CreateTree (&T) • 清空以T为根的树 ClearTree(&T) • 判断树是否为空 TreeEmpty(T) • 获取给定结点的第i个孩子 Child(T,node,i) • 获取给定结点的双亲 Parent(T,node) • 遍历树 TraverseTree(T,visit( )) • 对树遍历的主要目的是将非线性结构通过遍历过程线性化,即获得一个线性序列。
6.2 二叉树(Binary Tree) 二叉树的递归定义 二叉树是n(n≥0)个结点的有限集合。 当n=0时,称为空二叉树; 当n>0时,有且仅有一个结点为二叉树的根,其余结点被分成两个互不相交的子集,一个作为左子集,另一个作为右子集,每个子集又是一个二叉树。
A A的TL B I C F J L B的TL D E G H K M
二叉树的特点 二叉树的特点 • 每个结点至多有二棵子树(即不存在度大于2的结点) • 二叉树的子树有左、右之分,且其次序不能任意颠倒
A A A A R L R L (2)只有根结点的二叉树 (1)空二叉树 (5)左、右子树均非空 (3)右子树为空 (4)左子树为空 二叉树的五种基本形态
A A A R L B I C F J L D E G H K M 二叉树和树 • 在二叉树中可定义类似树中的概念。 • 二叉树不是树的特殊情形,它们是两个概念。 • 树和二叉树之间最主要的差别是 • 二叉树中结点的子树要区分为左子树和右子树,即使在结点只有一棵子树的情况下也要明确指出该子树是左子树还是右子树。
A A A A A A A B B B B B B B C C C C C C C 二叉树和树 以三个结点的树为例 三个结点的树(两棵) 三个结点的二叉树(五棵)
A 假设对所有 j(1j<i)命题成立 即第j 层上至多有 个结点; B I 则第i-1 层至多有 个结点; C F J L D E G H K M 二叉树的性质 性质1在二叉树的第 i 层最多有2i -1个结点。 (i 1) 证明:用归纳法证明 i=1时,只有一个根结点: 又二叉树每个结点的度至多为2, 第i 层上最大结点数是第i-1 层的2倍,即
A B I C F J L D E G H K M 二叉树的性质 性质2深度为 k 的二叉树最多有2k-1个结点。 (k 1) 证明: 20 + 21 + 22 + … + 2k-1 = 2k-1
A B I C F J L D E G H K M 二叉树的性质 性质3对任何一棵二叉树, 如果其叶结点有n0 个, 度为2的非叶结点有n2个, 则有 n0=n2+1 证明: 设度为1的结点有 n1个,总结点个数为 n,总边数为 e,则根据二叉树的定义, n = n0 + n1 + n2 e = 2n2 + n1 = n - 1 2n2 + n1 = n0 + n1 + n2 - 1 n2 = n0 – 1 n0 = n2 + 1
特殊形式的二叉树 定义1满二叉树 (Full Binary Tree) 一棵深度为 k且有2k-1个结点的二叉树 特点 每一层上的结点数都是最大数。
1 1 2 2 3 3 4 4 5 5 6 6 7 7 11 12 13 14 15 8 8 9 9 10 10 特殊形式的二叉树 定义2完全二叉树 (Complete Binary Tree) • 深度为h、n个结点的二叉树,除第h层外,其它各层 (0 h-1) 的结点数都达到最大个数,第h层从右向左连续缺若干结点,即其每一个结点都与深度为h的满二叉树中编号从1至n的结点一一对应。 特点 • 叶子结点只可能在层次最大的两层上出现; • 对任一结点,若其右子树的最大层次为 l ,则其左子树的最大层次必为 l 或 l +1。
1 2 3 1 4 5 2 3 4 5 6 7 6 7 8 9 10 11 12 13 14 15 1 1 2 3 2 3 4 5 6 7 6 4 5 8 9 10 11 12 满二叉树 非完全二叉树 非完全二叉树 完全二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 上面k-1层结点数 第k层结点数 2 3 4 5 6 7 8 二叉树的性质 性质4具有 n个结点的完全二叉树的深度为log2n + 1 证明: 设完全二叉树的深度为 k,则有 2k-1 - 1 < n 2k- 1 变形 2k-1n < 2k 取对数k-1 log2n <k 因此有 k = log2n + 1
1 i 2 3 2i 2i+1 5 6 7 4 8 9 10 二叉树的性质 性质5如对一棵有n个结点的完全二叉树的结点自顶向 下,同一层自左向右连续编号1, 2, …, n,则对 任一结点 i ( 1 i n),则有以下关系: • 若i = 1, i 无双亲;i > 1, i 的双亲为i /2; • 若2i > n, i 无左孩子,否则其左孩子为 2i ; • 若2i+1>n, i 无右孩子,否则其右孩子为 2i+1;
1 2 3 证明 • 若2i > n, i 无左孩子,否则其左孩子为 2i ; • 若2i+1>n, i 无右孩子,否则其右孩子为 2i+1; 归纳法证明: • i=1: 则其左孩子为结点2,右孩子为结点3。 若2 > n,即不存在结点2,此时结点 i 无左孩子; 若3 > n,即不存在结点3,此时结点 i 无右孩子;
证明(续) • 若2i > n, i 无左孩子,否则其左孩子为 2i ; • 若2i+1>n, i 无右孩子,否则其右孩子为 2i+1; 归纳法证明: • i>1:(分二种情况证明) • 设 i 为第 j 层的某个结点但不是最后一个结点,当 2i>n 时无左孩子,否则其左孩子为 2i; 当 2i+1>n 时无右孩子,否则其右孩子为 2i+1。 • 设 i 为第 j 层的最后一个结点,且, 当 2i>n 时无左孩子,否则其左孩子为 2i; 当 2i+1>n 时无右孩子,否则其右孩子为 2i+1。
第 j-1 层 i /2 第 j 层 i i+1 第 j +1 层 2i+2 2i+3 2i 2i+1 证明(续) • 设 i 为第 j 层的某个结点不是最后一个结点,即2j-1 i< 2j-1, 且 2i+1>n,则其左孩子为 2i;右孩子为 2i+1。 那么, 编号 i+1 的结点为该结点的右兄弟或堂兄弟; 若它的左孩子存在,则编号必为 2i+2=2(i+1); 若它的右孩子存在,则编号必为 2i+3=2(i+1)+1。
第 j 层 … i 第 j +1 层 … i+1 2i 2i+1 第 j +2 层 2i+2 2i+3 证明(续) • 设 i 为第 j 层的最后一个结点,即i=2j-1, 且2i+1>n,则其左孩子为2i;右孩子为2i+1。 那么, 编号i+1的结点必为j +1层的第一个结点,则i+1=2j ; 若其左孩子必为第 j+2层的第一个结点,编号为2j+1=22j=2(i+1);若2(i+1)> n, i+1无左孩子; 其右孩子必为第 j+1层的第二个结点,编号为2(i+1)+1; 若2(i+1)+1>n, i+1无右孩子。
1 50 51 100 二叉树性质应用例 已知完全二叉树有100个结点,则该二叉树有多少个叶子结点? 若认为每个结点均已编号,则最大的编号为100,其父结点编号为50(见图4-9),从51到100均为叶子,因此叶子数为100-50=50。如下图:
二叉树的基本操作 • 构造一棵二叉树 CreateBiTree ( &BT) • 清空以BT为根的二叉树 ClearBiTree(&BT) • 判断二叉树是否为空 BiTreeEmpty(BT) • 获取给定结点的左孩子 LeftChild(BT,e) • 获取给定结点的右孩子 RightChild(BT,e) • 获取给定结点的双亲 Parent(BT,e) • 遍历二叉树 Traverse(BT)
二叉树的存储结构 • 顺序存储结构 • 链式存储结构
1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j a b c e f g d h i j 1、顺序存储结构 • 实现: • 按满二叉树的结点层次编号,用一组地址连续的存储单元依次存放二叉树中的数据元素,即编号为i的结点存储在数组中下标为i的元素中。
a b c d e f g 1 2 3 4 5 6 7 8 9 10 11 a b c d e 0 0 0 0 f g
a b c d 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 a 0 b 00 0 c 00 0 0 0 0 0 d
顺序存储结构的特点及类型定义 • 特点: • 结点间关系蕴含在其存储位置中 • 浪费空间,适于存满二叉树和完全二叉树 • 类型定义: #define MAX_TREE_SIZE 100// 二叉树的最大结点数 typedef struct {ElemType elem[MAX_TREE_SIZE]; //根存储在下标为1的数组单元中 int n; //当前完全二叉树的结点个数 } SqBiTree;
基本操作 (1)构造一棵完全二叉树 void CreateBTree(SqBiTree &BT, ElemType elem[ ], int n){ if (n>=MAX_TREE_SIZE) n=MAX_TREE_SIZE-1; for (i=1; i<=n;i++) BT.elem[i]=elem[i-1]; BT.n=n;}
基本操作 (2)获取给定结点的左孩子 int LeftCHild(SqBiTree BT, int node) { if (2*node>BT.n) return ERROR; else return 2*node; }
基本操作 (3)获取给定结点的双亲 int Parent(SqBiTree BT, int node) { if (1<=node && node<=BT.n) return node/2; else return -1; }
2、链式存储结构 • 设计不同的结点结构构成不同的链式存储结构。 • 二叉链表 • 三叉链表
leftChild data rightChild data RIGHTCHILD LEFTCHILD 存储结点值的数据域data 二叉链表 • 结点结构 指向左孩子结点的指针 指向右孩子结点的指针 • 二叉链表
Lchild data Rchild 类型定义 typedef struct BiTNode { TElemType data; struct BiTNode *Lchild,*Rchild; } BiTNode, *BiTree;
A G F E C B A D B ^ ^ ^ C D ^ ^ E F G 空指针个数:2n0+1n1+0n2 =2n0+1n1 =n0+n1+n0 =n0+n1+n2+1 =n+1 ^ ^ ^ 在n个结点的二叉链表中,有n+1个空指针域
leftChild data parent rightChild parent data rightChild leftChild 三叉链表 • 结点结构 指向双亲的指针 • 三叉链表
Lchild data parent Rchild 类型定义 typedef struct BiTNode { TElemType data; struct BiTNode *Lchild,*Rchlid, *parent; } BiTNode, *BiTree;
A B C D E F G A B ^ ^ ^ C D ^ ^ E F G ^ ^ ^ ^