树的基本概念和术语 二叉树的概念及性质 二叉树的存储结构 顺序存储...
description
Transcript of 树的基本概念和术语 二叉树的概念及性质 二叉树的存储结构 顺序存储...
树
重点1. 树的基本概念和术语2. 二叉树的概念及性质3. 二叉树的存储结构
1. 顺序存储2. 链式存储
4. 遍历二叉树1. 递归算法2. 非递归算法
5. 线索二叉树6. 树的应用:哈夫曼树
7.1 7.1 树的概念和性质树的概念和性质
• 树的定义(树的定义( P85P85 )) 树:树: nn(( nn≥0≥0 ))个个结点结点的有限的有限集合集合。当。当 nn== 00
时,称为空树;任意一棵非空树满足以下条件:时,称为空树;任意一棵非空树满足以下条件:– ⑴ ⑴ 有且仅有一个特定的称为有且仅有一个特定的称为根根的结点;的结点;– ⑵ ⑵ 当当 nn>> 11 时,除根结点之外的其余结点被分成时,除根结点之外的其余结点被分成
mm(( mm>0>0 ))个个互不相交互不相交的有限集合的有限集合 TT11,,TT22,… ,,… ,TTmm ,,其中其中每个集合又是一棵树,并称为这个根结点的每个集合又是一棵树,并称为这个根结点的子树子树。。
• 树的定义是采用递归方法树的定义是采用递归方法
树的形式定义• D={ai | ai ElemSet∈ , i=1,…,n}
• 二元关系 S 的定义:• 当 n=1 时, S=φ ;• 当 n>1 时:
• 结点的度:结点的度:结点所拥有的子树的个数。结点所拥有的子树的个数。• 叶子结点:叶子结点:度为度为 00 的结点,也称为终端结点。的结点,也称为终端结点。• 分支结点:分支结点:度不为度不为 00 的结点,也称为非终端结点。的结点,也称为非终端结点。• 树的度:树的度:树中各结点度的最大值。树中各结点度的最大值。• 孩子、双亲:孩子、双亲:树中某结点子树的根结点称为这个结点树中某结点子树的根结点称为这个结点
的的孩子结点孩子结点,这个结点称为它孩子结点的,这个结点称为它孩子结点的双亲结点双亲结点;;• 兄弟:兄弟:具有同一个双亲的孩子结点互称为兄弟。具有同一个双亲的孩子结点互称为兄弟。• 路径:路径:如果树的结点序列如果树的结点序列 nn11, , nn22, …, , …, nnkk 有如下关系:结有如下关系:结点点 nnii是是 nni+1i+1 的双亲(的双亲( 1<=1<=ii<<kk ),则把),则把 nn11, , nn22, …, , …, nnkk 称为称为一条由一条由 nn11至至 nnkk 的的路径路径;路径上经过的边的个数称为;路径上经过的边的个数称为路路径长度径长度。。
树的基本术语(树的基本术语( P86P86 ))
• 祖先、子孙:祖先、子孙:在树中,如果有一条路径从结点在树中,如果有一条路径从结点 xx到结点到结点 yy ,,那么那么 xx 就称为就称为 yy 的祖先,而的祖先,而 yy 称为称为 xx的子孙。的子孙。
• 结点所在层数:结点所在层数:根结点的层数为根结点的层数为 11 ;对其余任何;对其余任何结点,若某结点在第结点,若某结点在第 ii 层,则其孩子结点在第层,则其孩子结点在第 i+1i+1层。层。
• 树的深度:树的深度:树中所有结点的最大层数,也称树中所有结点的最大层数,也称高度高度。。• 有序树、无序树:有序树、无序树:如果一棵树中结点的各子树从如果一棵树中结点的各子树从
左到右是有次序的,称这棵树为左到右是有次序的,称这棵树为有序树有序树;反之,;反之,称为称为无序树无序树。。
• 森林:森林: mm ( (mm≥0)≥0) 棵互不相交的树的集合。棵互不相交的树的集合。
树的基本术语(续)树的基本术语(续)
• 研究二叉树的意义?研究二叉树的意义?– 二叉树的结构相对简单,其运算也自然简单,二叉树的结构相对简单,其运算也自然简单,
便于初学者入门。便于初学者入门。– 由于多叉树可以借助一定的规则转换为二叉树,由于多叉树可以借助一定的规则转换为二叉树,
因此二叉树结构在应用中具有非常重要的地位。因此二叉树结构在应用中具有非常重要的地位。
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
• 二叉树的定义(二叉树的定义( P88P88 ))– 二叉树是二叉树是 nn(( n≥0n≥0 )个结点的有限集合,该集)个结点的有限集合,该集
合或者为合或者为空集空集(称为空二叉树),或者由一个(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的根结点和两棵互不相交的、分别称为根结点的左子树左子树和和右子树右子树的二叉树组成。的二叉树组成。
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
• 二叉树的特点二叉树的特点– 每个结点的度只可能是每个结点的度只可能是 00,, 11,, 22 ;;– 二叉树是有序树,即使某结点只有一棵子树,二叉树是有序树,即使某结点只有一棵子树,
也要区分该子树是左子树还是右子树。也要区分该子树是左子树还是右子树。
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
• 二叉树的二叉树的 55 种基本形态(种基本形态( P89P89 ))
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
例:画出具有例:画出具有 33 个结点的树和具有个结点的树和具有 33 个结点的二叉树的形态个结点的二叉树的形态
二叉树和树是两种树结构。二叉树和树是两种树结构。
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
• 特殊的二叉树特殊的二叉树• 满二叉树满二叉树
– 在一棵二叉树中,如果所有分支结点都存在左在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上。子树和右子树,并且所有叶子都在同一层上。
• 满二叉树的特点:满二叉树的特点:– 叶子只能出现在最下一层;叶子只能出现在最下一层;– 只有度为只有度为 00 和度为和度为 22 的结点。的结点。
• 完全二叉树:完全二叉树:深度为深度为 KK 的,有的,有 nn 个结点的二叉树,个结点的二叉树,当且仅当其每一个结点都与深度为当且仅当其每一个结点都与深度为 KK 的满二叉树的满二叉树从编号从编号 11到到 nn 的结点一一对应是时,称为完全二的结点一一对应是时,称为完全二叉树。叉树。
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
• 性质性质 11 ::在一棵二叉树中,如果叶子结点数为在一棵二叉树中,如果叶子结点数为nn00 ,,度为度为 22 的结点数为的结点数为 nn22 ,,则有则有 : : nn00== nn22++11。。
• 性质性质 22 ::二叉树的第二叉树的第 ii 层上最多有层上最多有 22ii-1-1 个结点个结点(( ii≥1≥1 )。)。
• 性质性质 33 ::一棵深度为一棵深度为 kk 的二叉树中,最多有的二叉树中,最多有22kk-1-1 个结点,最少有个结点,最少有 kk 个结点。个结点。
7.2 7.2 二叉树的概念和性质 二叉树的概念和性质 p89p89
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
7.2 7.2 二叉树的概念和性质二叉树的概念和性质
性质性质 44 具有具有 nn 个结点的完全二叉树的深度为 个结点的完全二叉树的深度为 loglog22n n
+1+1。。性质性质 55 对一棵具有对一棵具有 nn 个结点的完全二叉树中从个结点的完全二叉树中从 11 开始按开始按层序编号,则对于任意的序号为层序编号,则对于任意的序号为 ii(( 1≤i≤n1≤i≤n ))的结点的结点(简称为结点(简称为结点 ii),),有:有:
(1)(1) 如果如果 ii>> 11 ,,则结点则结点 ii 的双亲结点的序号为 的双亲结点的序号为 ii/2/2 ;;如果如果 ii== 11 ,,则结点则结点 ii 是根结点,无双亲结点。是根结点,无双亲结点。 (2)(2) 如果如果 22ii≤≤nn ,,则结点则结点 ii 的左孩子的序号为的左孩子的序号为 22ii;; 如果如果 22ii>> nn ,,则结点则结点 ii 无左孩子。 无左孩子。 (3)(3) 如果如果 22ii++ 1≤n1≤n ,,则结点则结点 ii 的右孩子的序号为的右孩子的序号为 22ii++ 11 如果如果 22ii++ 11>> nn ,,则结点 则结点 ii 无右孩子。无右孩子。
7.2 7.2 二叉树的概念和性质二叉树的概念和性质性质六:给定 n 个结点,能构成 H(n) 种不同
的二叉树:
1
1*
!!*
2
nnn
n)!(
考研真题1. 具有 3 个结点的二叉树有 ( ) 种2. 有 10 个叶子结点的二叉树中有( )个度为 2
的结点。3. 二叉树有 10 个度为 2 的结点, 5 个度为 1 的结
点,则度为 0 的结点个数是( )4. 一棵完全二叉树有 1001 个结点,其中叶子结点
的个数是( )5. 高度为 4 的完全二叉树至少有( )个结点6. 高度为 5 的完全二叉树至多有( )个结点
7.3.17.3.1 二叉树的顺序存储结构二叉树的顺序存储结构(( P91P91 ))
• 二叉树的顺序存储结构就是用一维数组存储二叉树二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的中的结点,并且结点的存储位置存储位置(下标)应能体现(下标)应能体现结点之间的结点之间的逻辑关系逻辑关系——父子关系。——父子关系。
• 如何利用数组下标来反映结点之间的逻辑关系如何利用数组下标来反映结点之间的逻辑关系 ??
– 二叉树的性质二叉树的性质 55 为二叉树的顺序存储指明了存储规则:为二叉树的顺序存储指明了存储规则:依照完全二叉树的结点编号次序,依次存放各个结点。依照完全二叉树的结点编号次序,依次存放各个结点。
– 注意:注意: C/C++C/C++ 中数组的起始地址为中数组的起始地址为 00 ,编号为,编号为 ii 的结点的结点存储在下标为存储在下标为 ii11 的单元内。的单元内。
– 完全二叉树完全二叉树和和满二叉树满二叉树中结点的序号可以唯一地反映出中结点的序号可以唯一地反映出结点之间的逻辑关系 。结点之间的逻辑关系 。
7.3.17.3.1 二叉树的顺序存储结构二叉树的顺序存储结构
#define MAX_TREE_SIZE 100 // 为最大结点数Typedef Telemtype SqBitree(MAX_TREE_SIZE);//0 号单元存储根结点, SqBitree bt;
7.3.17.3.1 二叉树的顺序存储结构二叉树的顺序存储结构• 非完全二叉树修补结构不存在的结点,用
特殊符号标识。
7.3.17.3.1 二叉树的顺序存储结构二叉树的顺序存储结构• 顺序存储结构适用于?• 完全二叉树
• 在最坏的情况下,一个深度为 K 且只有 K个结点的单支树,树中不存在度为 2 的结点,却需要长度为 2k-1 的一维数组
7.3.27.3.2 二叉树的链式存储结构二叉树的链式存储结构(( P92P92 ))
• 基本思想:基本思想:令二叉树的每个结点对应一个链表结令二叉树的每个结点对应一个链表结点,链表结点除了存放与二叉树结点有关的数据点,链表结点除了存放与二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。信息外,还要设置指示左右孩子的指针。
结点结构:结点结构: lchildlchild datadata rchildrchild
其中,其中, datadata ::数据域,存放该结点的数据信息;数据域,存放该结点的数据信息; lchildlchild ::左指针域,存放指向左孩子的指针;左指针域,存放指向左孩子的指针; rchildrchild ::右指针域,存放指向右孩子的指针。右指针域,存放指向右孩子的指针。
struct BiNode struct BiNode { T data; // { T data; // 结点数据结点数据 BiNode<T> *lchild; // BiNode<T> *lchild; // 左孩子的指针左孩子的指针 BiNode<T> *rchild; // BiNode<T> *rchild; // 右孩子的指针 右孩子的指针 };};
lchildlchild datadata rchildrchild
左孩子结点左孩子结点 右孩子结点右孩子结点
二叉链表结构定义二叉链表结构定义
G
FED
B
A
A
B C
D E F
G
∧
∧
∧ ∧
∧ ∧ ∧ ∧
C
具有具有 nn 个结点的二叉链表中,有多少个空指针?个结点的二叉链表中,有多少个空指针?
7.3.27.3.2 二叉树的链式存储结构二叉树的链式存储结构
G
FED
B
A
A
B C
D E F
G
∧
∧
∧ ∧
∧ ∧ ∧ ∧
C
具有具有 nn 个结点的二叉链表中,有个结点的二叉链表中,有 nn+1+1 个空指针。个空指针。
7.3.27.3.2 二叉树的链式存储结构二叉树的链式存储结构
7.47.4 二叉树的遍历二叉树的遍历
二叉树的遍历是指从根结点出发,按照某种二叉树的遍历是指从根结点出发,按照某种次序次序访访问二叉树中的所有结点,使得每个结点被访问一次问二叉树中的所有结点,使得每个结点被访问一次且仅被且仅被访问访问一次。一次。
二叉树遍历操作的结果?二叉树遍历操作的结果? 非线性结构线性化非线性结构线性化
抽象操作,抽象操作,可以是对结点进行的各种可以是对结点进行的各种处理,这里处理,这里简化为输出结点的数据。简化为输出结点的数据。
前序遍历前序遍历中序遍历中序遍历后序遍历后序遍历层序遍历层序遍历
如果限定先左后右,则二叉树遍历方式有三种:如果限定先左后右,则二叉树遍历方式有三种:前序前序:: DLRDLR
中序中序:: LDRLDR
后序后序:: LRDLRD
层序遍历层序遍历:按二叉树的层序编号的次序访问各结点。:按二叉树的层序编号的次序访问各结点。
考虑二叉树的组成:考虑二叉树的组成: 根结点根结点 DD
左子树左子树 LL
右子树右子树 RR
二二叉叉树树
7.4 7.4 二叉树的遍历二叉树的遍历
前序遍历的概念前序遍历的概念①①若二叉树为空,则空操作返回;若二叉树为空,则空操作返回;
((否则)否则)
②②访问根结点;访问根结点;
③③前序前序遍历遍历根根结点的左子树;结点的左子树;
④④前序前序遍历遍历根根结点的右子树。结点的右子树。
前序遍历序列:前序遍历序列: A B D G C E FA B D G C E F
A
B C
D E F
G
7.4 7.4 二叉树的遍历二叉树的遍历
前序遍历前序遍历——递归算法——递归算法
Void trave (BTNode *p)Void trave (BTNode *p){ if (p!=Null){ if (p!=Null) visit(p);visit(p); Trave (p->lchild);Trave (p->lchild); Trave (p->rchild);Trave (p->rchild);}//}//假设 假设 visit()visit() 已定义过,包含对结点已定义过,包含对结点 PP 的各种访问操作,如的各种访问操作,如打印出打印出 PP 对应的数值 对应的数值 // States printelem( Telemtype e) // States printelem( Telemtype e) { Print(e); return OK; }{ Print(e); return OK; }
中序遍历的概念中序遍历的概念①①若二叉树为空,则空操作返回;若二叉树为空,则空操作返回;
((否则)否则)
②②中序中序遍历遍历根根结点的左子树;结点的左子树;
③③访问根结点;访问根结点;
④④中序中序遍历遍历根根结点的右子树。结点的右子树。
中序遍历序列:中序遍历序列: D G B A E C FD G B A E C F
A
B C
D E F
G
7.4 7.4 二叉树的遍历二叉树的遍历
中序遍历中序遍历——递归算法——递归算法void inordervoid inorder (BTNode *p) (BTNode *p){ if (p==NULL) return; // ①{ if (p==NULL) return; // ① InOrder(p->lchild); // ③ InOrder(p->lchild); // ③ cout << p->data; // ②cout << p->data; // ② InOrder(p->rchild); // ④InOrder(p->rchild); // ④}}
后序遍历的概念后序遍历的概念①①若二叉树为空,则空操作返回;若二叉树为空,则空操作返回;
(否则)(否则)
②②后序后序遍历遍历根根结点的左子树;结点的左子树;
③③后序后序遍历遍历根根结点的右子树。结点的右子树。
④④访问根结点;访问根结点;
后序遍历序列:后序遍历序列: G D B E F C AG D B E F C A
A
B C
D E F
G
7.4 7.4 二叉树的遍历二叉树的遍历
后序遍历后序遍历——递归算法——递归算法
Void PostOrder (BTNode *p)Void PostOrder (BTNode *p){ if (p==NULL) return; // { if (p==NULL) return; // ①① PostOrder(p->lchild); // PostOrder(p->lchild); // ③ ③ PostOrder(p->rchild); // PostOrder(p->rchild); // ④④ cout << p->data; // ②cout << p->data; // ②}}
Void trave (BTNode *p){ if (p!=Null) {// (1) Trave (p->lchild); // (2) Trave (p->rchild); // (3)}// 假设 visit() 已定义过, visit(p); 放在不同的位置,表示
不同的遍历方式。
7.4 7.4 二叉树的非递归遍历二叉树的非递归遍历
• 中序遍历二叉树的非递归算法:1. 指向根结点的指针,当栈顶记录中的指针非空时,应遍历左
子树,即指向左子树根的指针进栈2. 若栈顶记录中的指针值为空,则应退到上一层,若是从左子
树返回,则应访问当前层,即栈顶记录中指针所指的根结点;3. 若是从右子树返回,则表明当前层的遍历结束,则应继续退
栈。• 思想:1. 开始根结点入栈,2. 循环执行如下操作:如果栈顶结点左孩子存在,则左孩子入
栈,如果栈顶结点左孩子不存在,则出栈并输出栈顶结点,然后检查其右孩子是否存在,如果存在,则右孩子入栈。
3. 当栈空时且已遍历完时算法结束。
Void inorder(BTNode *bt){ BTNode *stack[maxsize];Int top=-1; BTNode *p;If(bt!=NULL) { p=bt; While (top!=-1|| P!=NULL) { while(P!=NULL)// 左孩子存在,则左孩子入栈,即各层结点的所有左孩子进栈 { stack[++top]=p; p=p->lchild; } If(top!=-1) // 在栈不空的情况下出栈左孩子 { p=stack[top--]; cout <<p->data<<" "; p=p->rchild; } } }}
7.4 7.4 二叉树的非递归遍历二叉树的非递归遍历• 用自己申请的栈来代替系统栈,先序遍历:Void preorder(BTNode *bt){ BTNode *stack[maxsize];Int top=-1; BTNode *p; If(bt!=NULL) { stack[++top]=bt; // 根结点先入栈 While (top!=-1) { p=stack[top--]; cout <<p->data<<" ";// 出栈并输入
栈点结点 If (p->rchild!=NULL) { stack[++top]= p->rchild; } If (p->lchild!=NULL) { stack[++top]= p->lchild; }
} }}
层次遍历的概念层次遍历的概念
二叉树的层次遍历是指从二二叉树的层次遍历是指从二叉树的第一层(即根结点)叉树的第一层(即根结点)开始,开始,从上至下从上至下逐层遍历,逐层遍历,在同一层中,则按在同一层中,则按从左到右从左到右的顺序对结点逐个访问。的顺序对结点逐个访问。
层序遍历序列:层序遍历序列: A B C D E F GA B C D E F G
A
B C
D E F
G
7.4 7.4 二叉树的遍历二叉树的遍历
1.1.队列队列 QQ 初始化;初始化;2. 2. 如果二叉树非空,将根指针入队;如果二叉树非空,将根指针入队;3. 3. 循环直到队列循环直到队列 QQ 为空为空 3.1 3.1 p=p=队列队列 QQ 的队头元素出队;的队头元素出队; 3.2 3.2 访问结点访问结点 pp 的数据域;的数据域; 3.3 3.3 若结点若结点 pp 存在左孩子,则将左孩子指针入队存在左孩子,则将左孩子指针入队
;; 3.4 3.4 若结点若结点 pp 存在右孩子,则将右孩子指针入队存在右孩子,则将右孩子指针入队
;;
二叉树的层次遍历二叉树的层次遍历算法算法
层次遍历层次遍历 A
B C
D E F
G
遍历序列:遍历序列:
A
A
B C
B
D
C
E F G
D E F G
7.4 7.4 二叉树的遍历二叉树的遍历
层次遍历层次遍历——非递归算法——非递归算法void level(BTNode *p)void level(BTNode *p) // // 层次遍历二叉树层次遍历二叉树{ int front, rear;{ int front, rear;
BTNode *que[maxsize] // BTNode *que[maxsize] // 定义一个循环队列,用于记录将要访问的层次上的结点定义一个循环队列,用于记录将要访问的层次上的结点 front=rear=0; //front=rear=0; // 初始化循环队列初始化循环队列 BTNode *q;BTNode *q;
If(p!=Null) If(p!=Null)
{ rear=(rear+1)%maxsize;{ rear=(rear+1)%maxsize;
Que[rear]=p; //Que[rear]=p; // 根结点入队根结点入队 While(front!=rear) //While(front!=rear) // 当队列为空时循环当队列为空时循环 { front=(front+1)%maxsize;{ front=(front+1)%maxsize;
Q=que[front];//Q=que[front];// 队头结点出队队头结点出队 Visit(q); Visit(q);
If(q->lchild!=Null) { rear=(rear+1)%maxsize; Que[rear]=q->lchild; }If(q->lchild!=Null) { rear=(rear+1)%maxsize; Que[rear]=q->lchild; }
If(q->rchild!=Null) { rear=(rear+1)%mazsize; Que[rear]=q->rchild; }If(q->rchild!=Null) { rear=(rear+1)%mazsize; Que[rear]=q->rchild; }
}}
}}
}}
若已知一棵二叉树的前序(或中序,或后序,或若已知一棵二叉树的前序(或中序,或后序,或层序)序列,能否唯一确定这棵二叉树呢?层序)序列,能否唯一确定这棵二叉树呢?
A
B
C
例:已知前序序列为例:已知前序序列为 ABCABC ,则可能的二叉树有,则可能的二叉树有 55 种。种。
A
B
C
二叉树的遍历的应用二叉树的遍历的应用
例:已知前序遍历序列为例:已知前序遍历序列为 ABCABC ,后序遍历序列,后序遍历序列为为 CBACBA ,则下列二叉树都满足条件。,则下列二叉树都满足条件。
A
B
C
A
B
C
若已知一棵二叉树的前序序列和后序序列,能否若已知一棵二叉树的前序序列和后序序列,能否唯一确定这棵二叉树呢?唯一确定这棵二叉树呢?
若已知一棵二叉树的前序序列和中序序列,能否若已知一棵二叉树的前序序列和中序序列,能否唯一确定这棵二叉树呢?怎样确定?唯一确定这棵二叉树呢?怎样确定?
例如:已知一棵二叉树的前序遍历序列和中序遍历例如:已知一棵二叉树的前序遍历序列和中序遍历序列分别为序列分别为 ABCDEFGHI ABCDEFGHI 和和 BCAEDGHFIBCAEDGHFI ,,如何如何构造该二叉树呢构造该二叉树呢 ??
前序:前序: AA B C D E F G B C D E F G H IH I中序:中序: B C B C A A E D G H F IE D G H F I
前序:前序: BB C C
中序:中序: BB C C
B C B C
D ED EF GF GH IH I
AA
前序: 前序: DD E F G H I E F G H I
中序: 中序: E E DD G H F I G H F I
AA
BB
CC
DD
EEFGFGHIHI
前序:前序: FF G G H IH I
中序:中序: G H G H FF I I
前序: 前序: DD E F G H I E F G H I
中序: 中序: E E DD G H F I G H F I
A
B
C
D
EFGHI
A
B
C
D
E F
IG
H
试题例:试找出分别满足下列条件的所有二叉树
① 先序序列和中序序列相同② 中序序列和后序序列相同③ 先序序列和后序序列相同④ 前序和后序遍历正好相反:
根据二叉树的前序和中序、中序和后序两对遍历序列都可以唯一确定这棵二叉树。
考研真题:
• 一棵二叉树的先序遍历序列是 A, B, C,D, E, F ,中序遍历序列为 C, B, A,E, D, F ,则后序遍历序列为:
C, B, E, F, D, A
考研真题 31 .已知一算术表达式的中缀形式为 A+B*C-D/E ,后缀形式为
ABC*+DE/- ,其前缀形式为 ( ) 【北京航空航天大学 1999 一、 3 ( 2分 )】
2 .算术表达式 a+b*( c+d/e )转为后缀表达式后为( )【中山大学 1999 一、
3. 设有一表示算术表达式的二叉树(见下图),【南京理工大学1999 一、 20( 2 分)】它所表示的算术表达式是( )
4. 设树 T 的度为 4 ,其中度为 1, 2, 3和 4 的结点个数分别为 4,2, 1, 1 则 T 中的叶子数为( )【南京理工大学 2000 一、 8 ( 1.5 分)】
5. 在下述结论中,正确的是( )【南京理工大学 99 一 4 ( 1分)
① 只有一个结点的二叉树的度为 0; ② 二叉树的度为 2 ; ③二叉树的左右子树可任意交换 ;
④ 深度为 K 的完全二叉树的结点个数小于或等于深度相同的满二叉树 A .①②③ B .②③④ C .②④ D .①④
E FD GA B
/
+ +
* -C*
考研真题 427. 利用二叉链表存储树,则根结点的右指针是( )。
【青岛大学 2001 五、 5 ( 2 分)】A .指向最左孩子 B .指向最右孩子 C .空
D .非空28 .对二叉树的结点从 1 开始进行连续编号,要求每个
结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用 ( ) 次序的遍历实现编号。【北京理工大学 2000 一、 4 ( 2 分)】
A .先序 B. 中序 C. 后序 D. 从根开始按层次遍历
29 .树的后根遍历序列等同于该树对应的二叉树的 ( ). 【北京理工大学 2001 六、 6 ( 2 分)】
A. 先序序列 B. 中序序列 C. 后序序列
考研真题 5
• 4. 设有一棵算术表达式树,用什么方法可以对该树所表示的表达式求值?
• 【中国人民大学 2001 二、 3(4 分)】• 5 .将算术表达式(( a+b) +c*(d+e)+
f ) *(g+h) 转化为二叉树。【东北大学 2000 三、 1 ( 4 分)】
小结
1. 树的基本概念和术语2. 二叉树的概念3. 二叉树的性质4. 二叉树的存储:顺序、链式5. 二叉树的遍历
倒装P 222, 2008 年阅读 1P3S1Adding to a woman’s increased dose of stress
chemicals , are her increased “opportunities” for stress.
P 240, 2008 P art A P2S4And only over the past 30years have scholars
examined history form the bottom up.
女性承受越来越多的压力的机会使她们因压力而产生的化学物质不断增加。
•仅仅是在过去 30 年里,学者们才开始从头仔细研究历史。
复习:
1. 树的基本概念和术语2. 二叉树的概念、满二叉树,完全二叉树3. 二叉树的性质4. 二叉树的存储:顺序、链式5. 二叉树的遍历
第二节:线索二叉树、森林、树的应用
• 二叉树遍历的应用• 线索二叉树• 树和森林
– 树的三种存储结构–森林与二叉树的转换– 树和森林的遍历
• Huffman 树
7.4 7.4 二叉树的遍历的应用二叉树的遍历的应用
• 二叉树的建立二叉树的建立– 遍历是二叉树各种操作的基础,可以在遍历的遍历是二叉树各种操作的基础,可以在遍历的
过程中进行各种操作,例如建立一棵二叉树。过程中进行各种操作,例如建立一棵二叉树。• 如何由一种遍历序列生成该二叉树?如何由一种遍历序列生成该二叉树?
– 为了建立一棵二叉树,将二叉树中每个结点的为了建立一棵二叉树,将二叉树中每个结点的空指针引出一个虚结点,其值为一特定值如空指针引出一个虚结点,其值为一特定值如““ *”*” ,以标识其为空,把这样处理后的二叉树,以标识其为空,把这样处理后的二叉树称为原二叉树的扩展二叉树。称为原二叉树的扩展二叉树。
扩展二叉树的前序遍历序列:扩展二叉树的前序遍历序列: A B A B ** D D ** ** C C ** **
D
B
A
C
* D
B
A
C
* *
* *
前序遍历前序遍历①① 若二叉树为空,则空操作返回;若二叉树为空,则空操作返回;(否则)(否则)②② 访问访问根结点;根结点;③③ 前序前序遍历遍历根结点的左子树;根结点的左子树;④④前序前序遍历遍历根结点的右子树。根结点的右子树。 D
B
A
C
前序创建前序创建①① 若输入为若输入为 *(*( 空空 )) ,则,则 root=NULLroot=NULL
(否则)(否则)②② 创建创建根结点;根结点;③③ 前序前序创建创建根结点的左子树;根结点的左子树;④④前序前序创建创建根结点的右子树。根结点的右子树。
由带空指针标记的先序序列构造二叉树的算法由带空指针标记的先序序列构造二叉树的算法
Status CreateBitree(Bitree &T){Status CreateBitree(Bitree &T){
//// 按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树//// 构造二叉链表表示的二叉树构造二叉链表表示的二叉树 TT
Scan(&ch);Scan(&ch);
if (ch=='*') T= NULL; // if (ch=='*') T= NULL; // 特殊数据标记空指针特殊数据标记空指针Else {Else {
if(!(T(BiTNode *)malloc(sizeof(BITNode))) if(!(T(BiTNode *)malloc(sizeof(BITNode)))
exit(overflow); // exit(overflow); // 创建新结点创建新结点 T->data=ch;//T->data=ch;// 生成根结点生成根结点
CreateBitree( T->lchild);// CreateBitree( T->lchild);// 创建左子树创建左子树 CreateBitree( T->lchild);// // CreateBitree( T->lchild);// // 创建右子树创建右子树
}return OK;}return OK;
}CreateBitree}CreateBitree
按先序序列建立二叉树的二叉链表的过程按先序序列建立二叉树的二叉链表的过程
7.5 7.5 二叉树的其他操作算法二叉树的其他操作算法 • 遍历二叉树是二叉树各种操作的基础,遍历算遍历二叉树是二叉树各种操作的基础,遍历算
法中对每个结点的访问操作可以是多种形式及法中对每个结点的访问操作可以是多种形式及多个操作,根据遍历算法的框架,适当修改访多个操作,根据遍历算法的框架,适当修改访问操作的内容,可以派生出很多关于二叉树的问操作的内容,可以派生出很多关于二叉树的应用算法。应用算法。– 计算二叉树的结点数 (计算二叉树的结点数 ( P104P104 ))– 计算二叉树的叶子节点数计算二叉树的叶子节点数– 计算二叉树的高度(计算二叉树的高度( P105P105 ))
计算一棵给定二叉树的所有结点数方法一:思想:遍历二叉树的时候,设全局变量 n计数。
• 方法二:先数左子树的结点,再计算右子数的结点
Int n; Void count(BTNode *p) { If(p!=NULL) { ++n; count(P->lchild); count(p->rchild); } }
int count(BTNode *p){ int n1,n2;If(p=NULL) return 0;else { n1= count(P->lchild); n2= count(p->rchild); return(n1+n2+1); } }
统计所有叶子点数
Int n; Void count(BTNode *p) { If(p!=NULL) { if (P->lchild==NULL&&p->rchild==NULL) ++n; count(P->lchild); count(p->rchild); } }
Int n; Void count(BTNode *p) { If(p!=NULL) { ++n; count(P->lchild); count(p->rchild); } }
思想:加一个判断条件,叶子结点左右子树都为空
统计所有叶子点数
{ int left,right; if(p==NULL) return(0); if(root->lchild==NULL && root->rchild==NULL) return 1; left= LeafCount(p->lchild); right=LeafCount(p->rchild); return left+right;}// 统计叶子结点的个数
int count(BTNode *p){ int n1,n2;If(p=NULL) return 0;else { n1= count(P->lchild); n2= count(p->rchild);
return(n1+n2+1); } }
求某个结点的层号思想:用遍历查找结点,在遍历的过程中,用
L 记录层号,当 P第一次来某结点或 P 将要由这个结点走向下层结点时, ++L ;当 P第三次来到这个结点或 P 将要由这个结点返回到上层结点时 --LInt L;
Void leno( BTNode *p, char x){ If(p !=NULL) { If(P->data==x) { cout<<L<<endl ; } ++L; Leno(P->lchild,x); Leno(P->rchild,x); --L; }}
求二叉树的深度
int Height( BTNode *p){ int left,right; if(p==NULL) return(0); left =Height(p->lchild); right=Height(p->rchild); if (left>right) return left+1; return right+1;}
7.6.1 7.6.1 线索二叉树的概念线索二叉树的概念
• 二叉树各种遍历算法,其本质是将树形结构转换为线性序二叉树各种遍历算法,其本质是将树形结构转换为线性序列,便于简化问题。列,便于简化问题。
• 在遍历序列中,每个结点都有自己的前驱和后继,求结点在遍历序列中,每个结点都有自己的前驱和后继,求结点的前驱和后继属于基本操作。快速地实现这个基本操作,的前驱和后继属于基本操作。快速地实现这个基本操作,对二叉树许多算法的性能有重要意义。对二叉树许多算法的性能有重要意义。
• 最简单的方法是在遍历过程中寻求答案,缺点是时间复杂最简单的方法是在遍历过程中寻求答案,缺点是时间复杂度等同遍历算法的时间复杂度度等同遍历算法的时间复杂度 O(n)O(n) ,这对于基本操作而,这对于基本操作而言,显然效率太低。言,显然效率太低。
• 为了实现在遍历序列中快速查找结点的前驱、后继,可以为了实现在遍历序列中快速查找结点的前驱、后继,可以利用二叉链表中空的指针域,利用二叉链表中空的指针域,指向结点在遍历序列中的前指向结点在遍历序列中的前驱、后继,这些指向前驱和后继的指针称为线索。驱、后继,这些指向前驱和后继的指针称为线索。
7.6.1 7.6.1 线索二叉树的概念线索二叉树的概念
• 线索:线索:将二叉链表中的空指针域指向前驱结点和将二叉链表中的空指针域指向前驱结点和后继结点的指针被称为线索;后继结点的指针被称为线索;
• 线索化:线索化:使二叉链表中结点的空链域存放其前驱使二叉链表中结点的空链域存放其前驱或后继信息的过程称为线索化;或后继信息的过程称为线索化;
• 线索二叉树:线索二叉树:加上线索的二叉树称为线索二叉树。加上线索的二叉树称为线索二叉树。
0: 0: lchildlchild 指向该结点的左孩子指向该结点的左孩子1: 1: lchildlchild 指向该结点的前驱结点指向该结点的前驱结点0: 0: rchildrchild 指向该结点的右孩子指向该结点的右孩子1: 1: rchildrchild 指向该结点的后继结点指向该结点的后继结点
ltag=ltag=
rtag=rtag=
结点结构结点结构
7.6.1 7.6.1 线索二叉树的概念线索二叉树的概念
lchild Ltag data rtag rchild
lchild Ltag data rtag rchild结点结构结点结构
7.6.1 7.6.1 线索二叉树的概念线索二叉树的概念
Typedef struct Typedef struct TBTNode TBTNode {{ char data;char data; Int ltag,rtag;Int ltag,rtag; Struct TBTNode Struct TBTNode *lchild;*lchild; Struct TBTNode Struct TBTNode *rchild;*rchild;};};
7.6.1 7.6.1 线索二叉树的概念线索二叉树的概念
• 二叉树的遍历方式有二叉树的遍历方式有 44 种,故有种,故有 44 种意义种意义下的前驱和后继,相应的有下的前驱和后继,相应的有 44 种线索二叉种线索二叉树:树:– ⑴ ⑴ 前序线索二叉树前序线索二叉树– ⑵ ⑵ 中序线索二叉树中序线索二叉树–⑶ ⑶ 后序线索二叉树后序线索二叉树–⑷ ⑷ 层序线索二叉树层序线索二叉树
线索二叉树的画法线索二叉树的画法
前序线索二叉树:前序线索二叉树:前序序列为:前序序列为: ABCD ABCD
中序线索二叉树:中序线索二叉树:中序序列为:中序序列为: BADC BADC
线索二叉树的画法线索二叉树的画法
后序线索二叉树:后序线索二叉树:后序序列为:后序序列为: BDCA BDCA
线索二叉树的画法线索二叉树的画法
中序线索链表上查找结点中序线索链表上查找结点 PP 的后继的后继• 对于中序线索二叉树上的任一结点,寻对于中序线索二叉树上的任一结点,寻找其中序的后继结点,有以下两种情况:找其中序的后继结点,有以下两种情况:– 11 )如果该结点的右标志为)如果该结点的右标志为 11 ,即无,即无
右孩子,那么其右指针域所指向的结右孩子,那么其右指针域所指向的结点便是它的后继结点;点便是它的后继结点;
– 22 )如果该结点的右标志为)如果该结点的右标志为 00 ,表明,表明该结点有右孩子,根据中序遍历的定该结点有右孩子,根据中序遍历的定义,它的后继结点是以该结点的右孩义,它的后继结点是以该结点的右孩子为根结点的子树的最左结点,即沿子为根结点的子树的最左结点,即沿着其右子树的左指针链向下查找,当着其右子树的左指针链向下查找,当某结点的左标志为某结点的左标志为 11 时,它就是所要时,它就是所要找的后继结点。找的后继结点。
中序线索链表上查找结点中序线索链表上查找结点 PP 的前驱的前驱
• 对于中序线索二叉树上的任一结点,寻找对于中序线索二叉树上的任一结点,寻找其中序的前驱结点,有以下两种情况:其中序的前驱结点,有以下两种情况:– 11 )如果该结点的左标志为)如果该结点的左标志为 11 ,即无左孩子,,即无左孩子,
那么其左指针域所指向的结点便是它的前驱结那么其左指针域所指向的结点便是它的前驱结点;点;
– 22 )如果该结点的左标志为)如果该结点的左标志为 00 ,即有左孩子,,即有左孩子,表明该结点有左孩子,根据中序遍历的定义,表明该结点有左孩子,根据中序遍历的定义,它的前驱结点是以该结点的左孩子为根结点的它的前驱结点是以该结点的左孩子为根结点的子树的最右结点,即沿着其左子树的右指针链子树的最右结点,即沿着其左子树的右指针链向下查找,当某结点的右标志为向下查找,当某结点的右标志为 11 时,它就是时,它就是所要找的前驱结点。所要找的前驱结点。
中序遍历对二叉树线索化的递归算法
Void Inthread (TBTNode *p, TBTNode *&pre){ if(p!=NULL) { TBTNode *pre=NULL; // 前驱结点指针 inthread(p->lchild, pre);//递归,左子树线索化 If(p->lchild==NULL) { p->lchild=pre; P->ltag=1;}//建立前驱线索 If(pre->rchild==NULL &&pre!=NULL ) {Pre->rchild=p;Pre->rtag=1;}//建立后继线索 Pre=p; // 前驱跟上,当前指针向前遍历 Inthread(p->rchild,pre); //递归,右子树线索化 Pre->rchild=NULL;Pre->rtag=1; }}
7.7.1 7.7.1 树的逻辑结构树的逻辑结构
• 树的遍历树的遍历– 从根结点出发,按照某种次序访问树中所有结点,使从根结点出发,按照某种次序访问树中所有结点,使得每个结点被访问一次且仅被访问一次。得每个结点被访问一次且仅被访问一次。
• 如何理解访问如何理解访问 ??– 抽象操作,可以是对结点进行的各种处理,这里简化抽象操作,可以是对结点进行的各种处理,这里简化
为输出结点的数据。为输出结点的数据。• 遍历的实质遍历的实质 ??
– 树结构(非线性结构)→线性结构。树结构(非线性结构)→线性结构。• 如何理解次序如何理解次序 ??
– 树通常有前序(根)遍历、后序(根)遍历和层序树通常有前序(根)遍历、后序(根)遍历和层序(次)遍历三种方式。(次)遍历三种方式。
树的先根遍历操作定义为:树的先根遍历操作定义为:若树为空,则空操作返回;否则若树为空,则空操作返回;否则⑴ ⑴ 访问根结点;访问根结点;⑵⑵ 按照从左到右的顺序前序遍历按照从左到右的顺序前序遍历根结点的每一棵子树。根结点的每一棵子树。
先根遍历序列:先根遍历序列:A B D E H I F C GA B D E H I F C G
A
CB
GFED
H I
树的后根遍历操作定义为:树的后根遍历操作定义为:若树为空,则空操作返回;否则若树为空,则空操作返回;否则⑴ ⑴ 按照从左到右的顺序后序遍历按照从左到右的顺序后序遍历根结点的每一棵子树;根结点的每一棵子树;⑵⑵ 访问根结点。访问根结点。
后根后根遍历序列:D H I E F B G C A
A
CB
GFED
H I
7.7.2 7.7.2 树的存储结构树的存储结构
• 实现树的存储结构,关键是什么实现树的存储结构,关键是什么 ??
– 如何表示树中结点之间的逻辑关系。如何表示树中结点之间的逻辑关系。
• 思考问题的出发点思考问题的出发点– 如何表示结点的双亲和孩子如何表示结点的双亲和孩子
7.7.2 7.7.2 树的存储结构树的存储结构
• 11 )双亲表示法)双亲表示法– 以一组连续空间存储树的结点,在每个结点中设一个以一组连续空间存储树的结点,在每个结点中设一个
指示器指示双亲结点的位置。 指示器指示双亲结点的位置。
7.7.2 7.7.2 树的存储结构树的存储结构
• 22 ))多叉链表表示法多叉链表表示法– 二叉树的二叉链表结构采用两个指针域存储结点可能二叉树的二叉链表结构采用两个指针域存储结点可能
有的孩子指针。树的多叉链表表示法延伸了这种结构有的孩子指针。树的多叉链表表示法延伸了这种结构设计:若树的度为设计:若树的度为 KK ,则在结点结构中设置,则在结点结构中设置 KK 个孩子个孩子指针域,使所有结点同构。指针域,使所有结点同构。
7.7.2 7.7.2 树的存储结构树的存储结构
• 33 )孩子链表表示法)孩子链表表示法– 每个结点的孩子以单链表的形式存储,每个结点的孩子以单链表的形式存储, nn 个结点有个结点有 nn
个孩子链表,个孩子链表, nn 个头指针又组成一个线性表,并以顺个头指针又组成一个线性表,并以顺序存储结构存储。 序存储结构存储。
7.7.2 7.7.2 树的存储结构树的存储结构
• 44 )孩子兄弟表示法)孩子兄弟表示法– 以二叉链表作为树的存储结构,链表中的结点的两个以二叉链表作为树的存储结构,链表中的结点的两个
指针分别指向该结点的第一个孩子结点和下一个兄弟指针分别指向该结点的第一个孩子结点和下一个兄弟结点。 结点。
森林与二叉树的转换
• 树与二叉树的转换• 森林转换成二叉树• 二叉树转换成森林
森林转换成二叉树
森林的遍历
树与森林• 树与二叉树的转换:给定一棵树,可以有唯一的二叉树与之对应,物理结构上,他们的二叉链表相同。结点的左子树保留,结点的第一个右子树变成该结点左子树的右孩子。
• 森林与二叉树的转换:是以孩子兄弟存储结构为基础的。• 先将森林中的树分别转换为二叉树,再将第二棵二叉树作
为第一棵二叉树的右子树,将第三棵二叉树作为第二棵二叉树的右子树……
• 树与森林的遍历:• 树的先根遍历,相当于对应二叉树的先根遍历• 树的后根遍历,相当于对应二叉树的中序遍历• 森林的先序遍历,对当二叉树的先序遍历• 森林的中序遍历,相当于对应二叉树的中序遍历
考研真题十
森林转为二叉树的三步:(1)连线(将兄弟结点相连,各树的根看作兄弟);(2)切线(保留最左边子女为独生子女,将其它子女分枝切掉);(3)旋转(以最左边树的根为轴,顺时针向下旋转 45 度)。其实经过(1)和(2),已转为二叉树,执行(3)只是为了与平时的二叉树的画法一致。
7.8 Huffman7.8 Huffman 树与树与 HuffmanHuffman 编码编码
问题的提出:问题的提出:
例:编制一个将百分制转换为五级分制的程序。例:编制一个将百分制转换为五级分制的程序。如:如:
if (a<60) b=”bad”;if (a<60) b=”bad”;
else if (a<70) b=”pass”else if (a<70) b=”pass”
else if (a<80) b=”general”else if (a<80) b=”general”
else if (a<90) b=”good”else if (a<90) b=”good”
else b=”excellent”; else b=”excellent”;
显然,此程序很简单,只要利用条件语句便可完成。如果显然,此程序很简单,只要利用条件语句便可完成。如果上述程序需反复使用,而且每次的输入量很大,则应考虑上述程序需反复使用,而且每次的输入量很大,则应考虑上述程序的质量问题,即其操作所需要的时间。因为在实上述程序的质量问题,即其操作所需要的时间。因为在实际中,学生的成绩在五个等级上的分布是不均匀的,假设际中,学生的成绩在五个等级上的分布是不均匀的,假设其分布规律如下表所示:其分布规律如下表所示:
分数 分数 00 -- 59 6059 60 -- 69 7069 70 -- 79 8079 80 -- 89 9089 90-- 100100
比例数 比例数 0.05 0.15 0.40 0.30 0.100.05 0.15 0.40 0.30 0.10
则则 80%80% 以上的数据需进行三次或三次以上的比较才能得出以上的数据需进行三次或三次以上的比较才能得出结果。结果。
相关概念相关概念
• 叶子结点的权值:叶子结点的权值:对叶子结点赋予的一个有意义对叶子结点赋予的一个有意义的数值量。的数值量。
• 二叉树的带权路径长度:二叉树的带权路径长度:设二叉树具有设二叉树具有 nn 个带权个带权值的叶子结点,从根结点到各个叶子结点的路径值的叶子结点,从根结点到各个叶子结点的路径长度与相应叶子结点权值的乘积之和。长度与相应叶子结点权值的乘积之和。记为:记为:
WPLWPL==
nn
kkkkkk llww
11
第第 kk 个叶子的权值;个叶子的权值;从根结点到第从根结点到第 kk 个叶子的路径长度个叶子的路径长度
• 编码:编码:给每一个对象标记一个二进制位串来表示给每一个对象标记一个二进制位串来表示一组对象。例:一组对象。例: ASCIIASCII ,指令系统,指令系统
• 等长编码:等长编码:表示一组对象的二进制位串的长度相表示一组对象的二进制位串的长度相等。等。
• 不等长编码:不等长编码:表示一组对象的二进制位串的长度表示一组对象的二进制位串的长度不相等。不相等。
不等长编码什么情况不等长编码什么情况下空间效率高?下空间效率高?
等长编码什么情况下等长编码什么情况下空间效率高?空间效率高?
相关概念相关概念
• 前缀编码:前缀编码:一组编码中任一编码都不是其一组编码中任一编码都不是其它任何一个编码的前缀 。它任何一个编码的前缀 。
• 前缀编码保证了在解码时不会有多种可能。前缀编码保证了在解码时不会有多种可能。
相关概念相关概念
哈夫曼树:哈夫曼树:给定一组具有确定权值的给定一组具有确定权值的叶子叶子结点,带权路径结点,带权路径长度长度最小的二叉树最小的二叉树。。例:给定例:给定 44 个叶子结点,其权值分别为个叶子结点,其权值分别为 {2{2,, 33,, 44,, 7}7} ,可以,可以构造出形状不同的构造出形状不同的多个二叉树。多个二叉树。
WPL=32 WPL=41 WPL=30WPL=32 WPL=41 WPL=30
2 3 4 7
2
3
4 7
7
4
2 3
7.8.1 Huffman7.8.1 Huffman 树树
哈夫曼树的特点:哈夫曼树的特点:1. 1. 权值越大的叶子结点越靠近根结点,而权值越小的叶子结权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点。 点越远离根结点。 2. 2. 只有度为只有度为 00 (叶子结点)和度为(叶子结点)和度为 22 (分支结点)的结点,(分支结点)的结点,不存在度为不存在度为 11 的结点的结点 ..
2 3 4 7
2
3
4 7
7
4
2 3
7.8.1 Huffman7.8.1 Huffman 树树
第第 11步:初始化步:初始化WW== {2{2,, 33,, 44,, 5}5} 哈夫曼树的构造过程哈夫曼树的构造过程
352 4
第第 22 步:选取与 合步:选取与 合并并
32
5
第第 33 步:删除 与加步:删除 与加入入
54
32
5
7.8.2 Huffman7.8.2 Huffman 树的构造树的构造
WW== {2{2,, 33,, 44,, 5}5} 哈夫曼树的构造过哈夫曼树的构造过程程
重复第重复第 22步步 54
32
5
54
9
重复第重复第 33步步 5
54
9
32
重复第重复第 22步步
重复第重复第 33步步
5
54
9
32
5
54
9
32
14
WW== {2{2,, 33,, 44,, 5}5} 哈夫曼树的构造过哈夫曼树的构造过程程
7.8.3 Huffman7.8.3 Huffman 树的应用树的应用 ———— HuffmanHuffman 编码编码
• 例:一组字符例:一组字符 {A, B, C, D, E, F, G}{A, B, C, D, E, F, G} 出现的出现的频率分别是频率分别是 {9, 11, 5, 7, 8, 2, 3}{9, 11, 5, 7, 8, 2, 3} ,设计最,设计最经济的编码方案。经济的编码方案。
9
5
2 3
5
10
19
11
26
87
15
45
0
0
0
0
0
0
1
1
1
1
1
1
A B
DC E
F G
编码方案:A: 00
B: 10
C: 010
D: 110
E: 111
F: 0110
G: 0111
考研真题:6 .要求二叉树按二叉链表形式存储,( 1 )写一个建立二叉树的算法。( 2 )写一个判别给定的二叉树是否是完全二叉树的算法。完全二叉树定义为:深度为 K ,具有 N 个结点的二叉树的每个结点都与深度为 K 的满二
叉树中编号从 1至 N 的结点一一对应。此题以此定义为准。【西北大学 2000 六 (12分 )】
类似本题的另外叙述有:( 1 )试写一算法判断某二叉树是否是完全二叉树。【青岛海洋大学 1999 六 (15分 )】( 2 )编程,判断一棵二叉链表表示的二叉树是否是完全二叉树。【南京航空航天大学
2001十 (10分 )】( 3 )编写算法判断一棵二叉树 BT 是否是完全二叉树。【北方交通大学 1997 八 (20分 )】
( 4 )假设二元树用左右链表示,试编写一算法,判别给定二元树是否为完全二元树?【哈尔滨工业大学 2000 十一 (14分 )】( 5 )设二叉树以二叉链表为存储结构,试给出判断一棵二叉树是否为满二叉树的算法,
用类 pascal 语言写为函数形式。【南开大学 1997 四 (16分 )】( 6 )试写一算法判别某二叉树是否是完全二叉树。【北京邮电大学 1994 九 (20分 )】
[ 题目分析 ] 二叉树是递归定义的,以递归方式建立最简单。BiTree Creat() //建立二叉树的二叉链表形式的存储结构{ ElemType x; BiTree bt;scanf(“%d”,&x); // 本题假定结点数据域为整型if(x==0) bt=null;else if(x>0) { bt=(BiNode *)malloc(sizeof(BiNode)); bt->data=x; bt->lchild=creat(); bt->rchild=creat(); } else error(“ 输入错误” ) ;return(bt); }// 结束 BiTree
考研真题:6 .要求二叉树按二叉链表形式存储,( 1 )写一个建立二叉树的算法。( 2 )写一个判别给定的二叉树是否是完全二叉树的算法。完全二叉树定义为:深度为 K ,具有 N 个结点的二叉树的每个结点都与深度为 K 的满二
叉树中编号从 1至 N 的结点一一对应。此题以此定义为准。【西北大学 2000 六 (12分 )】
类似本题的另外叙述有:( 1 )试写一算法判断某二叉树是否是完全二叉树。【青岛海洋大学 1999 六 (15分 )】( 2 )编程,判断一棵二叉链表表示的二叉树是否是完全二叉树。【南京航空航天大学
2001十 (10分 )】( 3 )编写算法判断一棵二叉树 BT 是否是完全二叉树。【北方交通大学 1997 八 (20分 )】
( 4 )假设二元树用左右链表示,试编写一算法,判别给定二元树是否为完全二元树?【哈尔滨工业大学 2000 十一 (14分 )】( 5 )设二叉树以二叉链表为存储结构,试给出判断一棵二叉树是否为满二叉树的算法,
用类 pascal 语言写为函数形式。【南开大学 1997 四 (16分 )】( 6 )试写一算法判别某二叉树是否是完全二叉树。【北京邮电大学 1994 九 (20分 )】
思想:判定是否是完全二叉树,可以使用队列,在遍历中利用完全二叉树“若某结点无左子女就不应有右子女”的原则进行判断。
int JudgeComplete(BiTree bt) //判断二叉树是否是完全二叉树 , 如是,返回 1 ,否则,返回0
{int tag=0; BiTree p=bt, Q[ ]; // Q 是队列,元素是二叉树结点指针,容量足够大if(p==null) return (1);QueueInit(Q); QueueIn(Q,p); //初始化队列,根结点指针入队while (!QueueEmpty(Q)) { p=QueueOut(Q); // 出队 if (p->lchild && !tag) QueueIn(Q,p->lchild); // 左子女入队 else {if (p->lchild) return 0; // 前边已有结点为空,本结点不空 else tag=1; //首次出现结点为空 if (p->rchild && !tag) QueueIn(Q,p->rchild); // 右子女入队 else if (p->rchild) return 0; else tag=1; } //whilereturn 1; } //JudgeComplete
[ 算法讨论 ] 完全二叉树证明还有其它方法。判断时易犯的错误是证明其左子树和右子数都是完全二叉树,由此推出整棵二叉树必是完全二叉树的错误结论。
考研真题24 .对于二叉树的链接实现 , 完成非递归的中序遍历过程。
【中山大学 1999 五、 (15分 )】类似本题的另外叙述有:( 1 )写出中序遍历二叉树的非递归算法及递推算法。【大
连海事大学 1996 六、 2 ( 10分 ) 】。( 2 )设计一个中序遍历算法,应用栈来存储树结点,要求
结点仅能进栈和出栈一次。(本题指中序遍历二叉树)【西安电子科技大学 1999计应用 四 (10分 )】( 3 )用非递归方式写出二叉树中序遍历算法。【山东科技
大学 2002 六、 2 (9分 )】
24. void InOrder(BiTree bt){BiTree s[ ],p=bt; //s 是元素为二叉树结点指针的栈,容量足够大 int top=0; while(p &&top>0) {while(p) {s[++top]=p; bt=p->lchild;} // 中序遍历左子树 if(top>0) {p=s[top--]; printf(p->data); p=p->rchild;} // 退栈,访问,转右子树 } }
考研真题 1
• 1 .从概念上讲,树,森林和二叉树是三种不同的数据结构,将树,森林转化为二叉树的基本目的是什么,并指出树和二叉树的主要区别。【西安电子科技大学 2001软件 二、 1( 5 分)】
• 2 .树和二叉树之间有什么样的区别与联系?• 【西北工业大学 1998 一、 3(4分 )】【厦门大学
2000 五、 2(3分 )】【燕山大学 2001 三、 1(5分 )】
• 3 .请分析线性表、树、广义表的主要结构特点,以及相互的差异与关联。
• 【大连海事大学 2001三 (10分 )】
1 .树的孩子兄弟链表表示法和二叉树二叉链表表示法,本质是一样的,只是解释不同,也就是说树(树是森林的特例,即森林中只有一棵树的特殊情况)可用二叉树唯一表示,并可使用二叉树的一些算法去解决树和森林中的问题。
树和二叉树的区别有三:一是二叉树的度至多为 2 ,树无此限制;二是二叉树有左右子树之分,即使在只有一个分枝的情况下, 也必须指出是左子树还是右子树,树无此限制;三是二叉树允许为空,树一般不允许为空
3 .线性表属于约束最强的线性结构,在非空线性表中,只有一个“第一个”元素,也只有一个“最后一个”元素;除第一个元素外,每个元素有唯一前驱;除最后一个元素外,每个元素有唯一后继。树是一种层次结构,有且只有一个根结点,每个结点可以有多个子女,但只有一个双亲(根无双亲),从这个意义上说存在一(双亲)对多(子女)的关系。广义表中的元素既可以是原子,也可以是子表,子表可以为它表共享。从表中套表意义上说,广义表也是层次结构。从逻辑上讲,树和广义表均属非线性结构。但在以下意义上,又蜕变为线性结构。如度为 1 的树,以及广义表中的元素都是原子时。另外,广义表从元素之间的关系可看成前驱和后继,也符合线性表,但这时元素有原子,也有子表,即元素并不属于同一数据对象。
第二节小结• 遍历二叉树
– 前序、中序、后序• 线索二叉树• 树和森林
– 树的三种存储结构– 森林与二叉树的转换– 树和森林的遍历
• 哈夫曼树• 有关树的算法
测试题目79 .给定集合 {15,3,14,2,6,9,16,17}(1)( 3 分)用□表示外部结点,用○表示内部结点,构造相应的 huffman 树:
(2) (2分 )计算它的带权路径长度:(3)( 3分 )写出它的 huffman 编码:(4)( 3分 )huffman 编码常用来译码,请用
语言叙述写出其译码的过程。【山东大学 1998 七、】【山东工业大学
2000 七、 (11分 )】(4) 常用哈夫曼树为通讯用的字符编码,本题中集合的数值解释为字符发生的频率(次数)。由哈夫曼树构造出哈夫曼编码。译码时,进行编码的“匹配”,即从左往右扫描对方发来的“编码串”,用字符编码去匹配,得到原来的元素(本题中的数)。
测试题目:算法• 假设二叉树采用二叉链存储结构,设计一
个算法,计算一棵给定二叉树的所有叶子结点数。
虚拟、复合谓语P 281, 2007 阅读 1 P1S1
• If you were to examine the birth certificates of every soccer player in 2006’s World Cup tournament, you would most likely find a noteworthy quirk: elite soccer players are more likely to have been born in the earlier months of the year than in the later months.
•如果你检查参加 2006 年世界杯足球锦标赛所有参赛运动员的出生证,很可能会发现一个值得注意的怪现象:优秀的足球运动员更可能出生于上半年,而不是下半年。
你的抱怨
• 一、没良师?• 二、没益友?• 三、没时间?• 四、没环境?
你的抱怨一、没良师?一、没良师?学习自修之道,学习基础知识,培养自学能力。• 教育家 B. F. Skinner斯金纳说“如果我们将学
过的东西忘得一干二净时,最后剩下来的东西就是教育的本质了。” 1.老师只是引路人2.中学与大学的区别3.要求高一点:例如,美国麻省理工学院 (MIT) 的开
放式课程4.网上资源无限丰富。选好方向学习。讲座?肥皂剧?生活大爆炸?老友记?
你的抱怨• 一、没良师?• 二、没益友?
1.你自己是否优秀?2.与外界接触
• 三、没时间?1.上课时间太多?2.学英语?学计算机语言?备考?学应用软件?
• 四、没环境?1.图书馆满有人占座?2.大家都在玩,自己学不下去?3.找借口?
如何达成目标?1. 周密的计划
– 有远期,中期和近期目标– 分解目标– 差距分析:有针对性的改善,如英语听力,
2. 坚毅的追求:3. 管理时间:
1. 重要的事和紧急的事。2. 给自己一个合理的最后期限
4. 马上执行:动起来,做下去。
考研真题 2
• 6. 一棵有 n(n>0) 个结点的 d 度树 , 若用多重链表表示 , 树中每个结点都有 d 个链域 , 则在表示该树的多重链表中有多少个空链域 ? 为什么 ? 【长沙铁道学院 1998 四、 1 (6分 )】
• 7. 一棵二叉树中的结点的度或为 0 或为 2 ,则二叉树的枝数为 2(n0-1) ,其中 n0 是度为0 的结点的个数。
• 【南京理工大学 1998 六、 (3分 ) 】
考研真题8 .若一棵二叉树具有 10 个度为 2 的结点, 5 个度为 1 的结
点,则度为 0 的结点个数是( )【北京工商大学 2001一 .7(3分 )】
9 .在一棵三元树中度为 3 的结点数为 2 个,度为 2 的结点数为 1 个,度为 1 的结点数为 2 个,则度为 0 的结点数为( )个【哈工大学 2001 二、 2 ( 2 分)】
11 .具有 10 个叶结点的二叉树中有( )个度为 2 的结点,【北京航空航天大学 2000 一、 5( 2分 )】
A. 8 B. 9 C. 10 D. ll12 .一棵完全二叉树上有 1001 个结点,其中叶子结点的个
数是( )【西安交通大学 1996 三、 2 (3分 )】A . 250 B . 500 C. 254 D. 505 E .以上答案
都不对
考研真题16. 有关二叉树下列说法正确的是( )【南京理工大学 2000 一、 11 ( 1.5
分)】A .二叉树的度为 2 B .一棵二叉树的度可以小于 2
C .二叉树中至少有一个结点的度为 2 D .二叉树中任何一个结点的度都为 217 .二叉树的第 I 层上最多含有结点数为( )【中山大学 1998 二、 7 ( 2 分)】【北京理工大学 2001 六、 5( 2 分)】A. 2I B . 2I-1-1 C . 2I-1 D. 2I -118. 一个具有 1025 个结点的二叉树的高 h 为( )【南京理工大学 1999 一、
19 ( 2 分)】A. 11 B. 10 C. 11至 1025之间 D. 10至 1024之间19 .一棵二叉树高度为 h, 所有结点的度或为 0 ,或为 2 ,则这棵二叉树最少有 ( ) 结点
A. 2h B. 2h-1 C. 2h+1 D. h+1 【南京理工大学 2001一、 11(1.5 分) 】
20 .对于有 n 个结点的二叉树 , 其高度为( )【武汉交通科技大学 1996 一、 5 (4分 )】
A. nlog2n B. log2n C . log2n|+1 D .不确定
考研真题21. 一棵具有 n 个结点的完全二叉树的树高度(深度)是( )【南京理工大
学 1996 一、 8 ( 2 分)】A . logn+1 B. logn+1 C . logn D. logn-122 .深度为 h 的满 m 叉树的第 k 层有( )个结点。 (1=<k=<h) 【北京航空航
天大学 2000 一、 4( 2 分)】A.mk-1 B.mk-1 C.mh-1 D.mh-123 .在一棵高度为 k 的满二叉树中,结点总数为( )【北京工商大学 2001
一、 3 (3分 )】A. 2k-1 B. 2k C. 2k-1 D . log2k+124 .高度为 K 的二叉树最大的结点数为( )。【山东大学 2001 二、 3 (1分 )】
A. 2k B. 2k-1 C. 2k -1 D. 2k-1-125. 一棵树高为 K 的完全二叉树至少有( )个结点【南京理工大学 1998 一、
3 ( 2 分)】A. 2k –1 B. 2k-1 –1 C. 2k-1 D. 2k26. 将有关二叉树的概念推广到三叉树,则一棵有 244 个结点的完全三叉树的
高度()A. 4 B. 5 C. 6 D. 7 【南京理工大学 2000 一、 5
1.5 分)】
考研真题:79 .给定集合 {15,3,14,2,6,9,16,17}(1)( 3 分)用□表示外部结点,用○表示内部结点,构造相应的 huffman 树:(2) (2分 )计算它的带权路径长度:(3)( 3分 )写出它的 huffman 编码:(4)( 3分 )huffman 编码常用来译码,请用语言叙述写出其译码的过程。【山东大学 1998 七、】【山东工业大学 2000 七、 (11分 )】类似本题的另外叙述有:( 1 ) 如果通信字符 a,b,c,d 出现频度分别为: 7, 5, 2, 4请画出哈夫曼树并给出相
应的哈夫曼编码。【青岛大学 2001 七、 1 ( 5分 )】( 2 )给定一组数列( 15,8,10,21,6,19,3 )分别代表字符 A,B,C,D,E,F,G 出现的频度,
试叙述建立哈夫曼树的算法思想,画出哈夫曼树,给出各字符的编码值,并说明这种编码的优点。
【青岛大学 2000 七、 (10分 )】( 3 )设通信中出现 5 中字符 A、 B、 C、 D、 E 对应的频率为 0.2,0.1,0.5,0.15,0.25
构造哈夫曼树,并给出对应字符的编码。【青岛大学 2002 四、 2 ( 10 分)】( 4 ) 设 A、 B、 C、 D、 E、 F 六个字母出现的概率分别为 7,19,2,6,32,3 。试写出
为这六个字母设计的 HUFFMAN 编码 , 并画出对应的 HUFFMAN树 . 【山东工业大学 1995 四 (10分 )】
( 5 )设用于通信的电文由 8 个字母组成 , 字母在电文中出现的频率分别为 :7,19,2,6,32,3,21,10 。试为这 8 个字母设计哈夫曼编码 .使用 0-7 的二进制表示形式是另一种编码方案 , 试比较这两种方案的优缺点。【南京航空航天大学 1999 四、 (10分 )】
(4) 常用哈夫曼树为通讯用的字符编码,本题中集合的数值解释为字符发生的频率(次数)。由哈夫曼树构造出哈夫曼编码。译码时,进行编码的“匹配”,即从左往右扫描对方发来的“编码串”,用字符编码去匹配,得到原来的元素(本题中的数)。
考研真题:类似本题的另外叙述有:( 6 )假设用于通讯的电文由 8 个字符组成,其出现的频率为 5,29,7,8,14,23,3,11 。试为这 8 个字符
设计哈夫曼编码。【燕山大学 1999 五、 (5分 )】( 7 )假设用于通信的电文由字符集 {a,b,c,d,e,f,g} 中的字母构成。它们在电文中出现的频度分别为
{0.31,0.16,0.10,0.08,0.11,,0.20,0.04}, 1) 为这 7 个字母设计哈夫曼编码;2 )对这 7 个字母进行等长编码,至少需要几位二进制数?哈夫曼编码比等长编码使电文总长压缩多
少?【北京邮电大学 2001 四、 2 ( 5分 )】( 8 )试构造一棵二叉树 ,包含权为 1,4,9,16,25,36,49,64,81,100等 10 个终端结点 , 且具有最小的加权路径长度 WPL。【北方交通大学 1993 年 五( 12分 )】
( 9 )带权结点为 {5,6,7,8,9} ,构造 Huffman 树,计算带权路径长度。【西北大学 2001 年三、 3】( 10 )以数据集 {2,5,7,9,13} 为权值构造一棵哈夫曼树,并计算其带权路径长度。【西安电子科技大学 1999计应用 一、 4 ( 5 分)】( 11 )假设用于通讯的电文仅由 8 个字母组成,字母在电文中出现的频率分别为
7,19,2,6,32,3, 21,10 。试为这 8 个字母设计哈夫曼编码。使用 0 7∽ 的二进制表示形式是另一 种编码方案。对于上述实例,比较两种方案的优缺点。【大连海事大学 1996 五、 2 (8分 ) 】。
( 12 )设用于通讯的电文仅由 8 个字母组成,他们在电文中出现的频率分别为 0.30, 0.07, 0.10,0.03, 0.20, 0.06,0.22, 0.02 ,试设计哈夫曼树及其编码。使用 0---7 的二进制表示形式是另一种编码方案。给出两种编码的对照表、带权路径长度 WPL 值并比较两种方案的优缺点。【厦门大学 1999 三、 3】
(13) 给定一组权值 2,3,5,7,11,13,17,19,23,29, 31, 37, 41 ,试画出用 Huffman 算法建造的Huffman 树。【吉林大学 2000 一、 2 ( 4分 )】
(14) 以数据集 {3,4,5,8,12,18,20,30} 为叶结点,构造一棵哈夫曼树,并求其带权路径长度。【山东师范大学 1996 五 5(2分 )】
考研真题八• 41. 证明,由一棵二叉树的前序序列和中序序列可唯一确定
这棵二叉树。设一棵二叉树的前序序列为 ABDGECFH ,中序序列为: DGBEAFHC 。试画出该二叉树。【浙江大学 1996 六、 (8分 )】
• 类似本题的另外叙述有:• (1) 证明:由一棵二叉树的前序序列和中序序列可唯一确定这
棵二叉树。• 【长沙铁道学院 1997 五、 2(10分 )】• ( 2 )证明:由二叉树的中序遍历序列和后序遍历序列可唯
一地确定出该二叉树。• 【华南理工大学 2001 一、 3 ( 4分 )】• ( 3 )二叉树已知其中序扫描序列和后序扫描序列如何确定
这一棵二叉树 , 并举例说明 . • 【山东大学 2001软件与理论 二 、 1 ( 4 分) 】