四章节二叉树.ppt
《四章节二叉树.ppt》由会员分享,可在线阅读,更多相关《四章节二叉树.ppt(162页珍藏版)》请在三一办公上搜索。
1、第四章 二叉树,任课教员:张 铭http:/,北京大学信息学院 版权所有,转载或翻印必究 Page 2,主要内容,4.1 二叉树的概念4.2 二叉树的主要性质 4.3 二叉树的抽象数据类型4.4 周游二叉树4.5 二叉树的实现4.6 二叉搜索树4.7 堆与优先队列4.8 Huffman编码树,北京大学信息学院 版权所有,转载或翻印必究 Page 3,4.1 二叉树的概念,4.1.1 二叉树的定义及相关概念4.1.2 满二叉树 完全二叉树 扩充二叉树,北京大学信息学院 版权所有,转载或翻印必究 Page 4,二叉树的定义,二叉树由结点的有限集合构成:或者为空集或者由一个根结点及两棵不相交的分别称
2、作这个根的左子树和右子树的二叉树(它们也是结点的集合)组成这是个递归的定义。二叉树可以是空集合,因此根可以有空的左子树或右子树,或者左右子树皆为空,北京大学信息学院 版权所有,转载或翻印必究 Page 5,二叉树的五种基本形态,(a)空(b)独根(c)空右(d)空左(e)左右都不空,北京大学信息学院 版权所有,转载或翻印必究 Page 6,满二叉树,如果一棵二叉树的任何结点,或者是树叶,或者恰有两棵非空子树,则此二叉树称作满二叉树,北京大学信息学院 版权所有,转载或翻印必究 Page 7,完全二叉树,若一颗二叉树最多只有最下面的两层结点度数可以小于2最下面一层的结点都集中在该层最左边的若干位置
3、上,则称此二叉树为完全二叉树在许多算法和算法分析中都明显地或隐含地用到完全二叉树的概念,北京大学信息学院 版权所有,转载或翻印必究 Page 8,完全二叉树,北京大学信息学院 版权所有,转载或翻印必究 Page 9,扩充二叉树,当二叉树里出现空的子树时,就增加新的、特殊的结点空树叶对于原来二叉树里度数为1的分支结点,在它下面增加一个空树叶对于原来二叉树的树叶,在它下面增加两个空树叶扩充的二叉树是满二叉树,新增加的空树叶(外部结点)的个数等于原来二叉树的结点(内部结点)个数加1,北京大学信息学院 版权所有,转载或翻印必究 Page 10,扩充二叉树,北京大学信息学院 版权所有,转载或翻印必究 P
4、age 11,扩充二叉树,外部路径长度E 从扩充的二叉树的根到每个外部结点的路径长度之和 内部路径长度I 扩充的二叉树里从根到每个内部结点的路径长度之和 E和I两个量之间的关系为 E=I+2n,北京大学信息学院 版权所有,转载或翻印必究 Page 12,4.2 二叉树的主要性质,1.满二叉树定理:非空满二叉树树叶数等于其分支结点数加1。证明:设二叉树结点数为n,叶结点数为m,分支结点数为b。有n(总结点数=m(叶)+b(分支)(公式4.1)每个分支,恰有两个子结点(满),故有2*b条边;一颗二叉树,除根结点外,每个结点都恰有一条边联接父结点,故共有n-1条边。即n-1=2b(公式4.2)由(公
5、式4.1),(公式4.2)得 n-1=m+b-1=2b,得出 m(叶)=b(分支)+1,北京大学信息学院 版权所有,转载或翻印必究 Page 13,4.2 二叉树的性质,2.满二叉树定理推论:一个非空二叉树的空子树(指针)数目等于其结点数加1。证明:设二叉树T,将其所有空子树换为树叶,记新 的扩充满二叉树为T。所有原来T的结点现在是T的分支结点。根据满二叉树定理,新添加的树叶数目等于T结点个数加1。而每个新添加的树叶对应T的一个空子树。因此T中空子树数目等于T中结点数加1。,北京大学信息学院 版权所有,转载或翻印必究 Page 14,4.2 二叉树的性质,3.任何一颗二叉树,度为0的结点比度为
6、2的结点多一个证明:设有n个结点的二叉树的度为0、1、2的结点数分别为=n0,n1,n2,则n=n0+n1+n2(公式4.3)设边数为e。因为除根以外,每个结点都有一条边进入,故n=e+1。由于这些边是有度为1和2的的结点射出的,因此e=n1+2n2,于是n=e+1=n1+2n2+1(公式4.4)因此由公式(1)(2)得 n0+n1+n2=n1+2n2+1 即 n0=n2+1,北京大学信息学院 版权所有,转载或翻印必究 Page 15,4.2 二叉树的性质,4.二叉树的第i层(根为第0层,i1)最多有2i个结点5.高度为k(深度为k-1。只有一个根结点的二叉树的高度为1,深度为0)的二叉树至多
7、有2k-1个结点6.有n个结点(n0)的完全二叉树的高度为log2(n+1)(深度为log2(n+1)-1),北京大学信息学院 版权所有,转载或翻印必究 Page 16,4.2 二叉树的性质,二叉树的高度定义为二叉树中层数最大的叶结点的层数加1二叉树的深度定义为二叉树中层数最大的叶结点的层数,北京大学信息学院 版权所有,转载或翻印必究 Page 17,4.3 二叉树的抽象数据类型,定义了二叉树的逻辑结构之后,我们需要考虑在二叉树逻辑结构之上的各种可能运算,这些运算应该适合二叉树的各种应用:二叉树的某些运算是针对整棵树的初始化二叉树合并两棵二叉树二叉树的大部分运算都是围绕结点进行的访问某个结点的
8、左子结点、右子结点、父结点访问结点存储的数据。,北京大学信息学院 版权所有,转载或翻印必究 Page 18,4.3 二叉树的抽象数据类型,二叉树结点抽象数据类型BinaryTreeNode是带有参数 T 的模板,T是存储在结点中的数据类型每个元素结点都有leftchild()和rightchild()左右子结点结构另外每个结点还包含一个数据域value()。为了强调抽象数据类型与存储无关,我们并没有具体规定该抽象数据类型的存储方式,北京大学信息学院 版权所有,转载或翻印必究 Page 19,4.3 二叉树的抽象数据类型,template class BinaryTreeNode/申明二叉树为结
9、点类的友元类,便于访问私有/数据成员 friend class BinaryTree;private:/二叉树结点数据域T element;/实现时,可以补充private的左子结点/右子结点定义,北京大学信息学院 版权所有,转载或翻印必究 Page 20,4.3 二叉树的抽象数据类型,public:BinaryTreeNode();/缺省构造函数 BinaryTreeNode(const T,北京大学信息学院 版权所有,转载或翻印必究 Page 21,4.3 二叉树的抽象数据类型,/设置当前结点的左子树 void setLeftchild(BinaryTreeNode*);/设置当前结点的右
10、子树 void setRightchild(BinaryTreeNode*);/设置当前结点的数据域 void setValue(const T,北京大学信息学院 版权所有,转载或翻印必究 Page 22,4.3 二叉树的抽象数据类型,二叉树的抽象数据类型的C+定义BinaryTree,没有具体规定该抽象数据类型的存储方式 template class BinaryTree private:/二叉树根结点指针BinaryTreeNode*root;/从二叉树的root结点开始/查找current结点的父结点BinaryTreeNode*GetParent(BinaryTreeNode*root
11、,BinaryTreeNode*current);,北京大学信息学院 版权所有,转载或翻印必究 Page 23,4.3 二叉树的抽象数据类型,public:BinaryTree(root=NULL);/构造函数 BinaryTree()DeleteBinaryTree(root);/析构函数 bool isEmpty()const;/判定二叉树是否为空树/返回二叉树根结点 BinaryTreeNode*Root()return root;/返回current结点的父结点 BinaryTreeNode*Parent(BinaryTreeNode*current);/返回current结点的左兄弟
12、 BinaryTreeNode*LeftSibling(BinaryTreeNode*current);,北京大学信息学院 版权所有,转载或翻印必究 Page 24,4.3 二叉树的抽象数据类型,/返回current结点的右兄弟BinaryTreeNode*RightSibling(BinaryTreeNode*current);/以elem作为根结点,leftTree作为树的左子树,/rightTree作为树的右子树,构造一棵新的二叉树void CreateTree(const T/前序周游二叉树或其子树void PreOrder(BinaryTreeNode*root);/中序周游二叉树或
13、其子树void InOrder(BinaryTreeNode*root);,北京大学信息学院 版权所有,转载或翻印必究 Page 25,4.3 二叉树的抽象数据类型,/后序周游二叉树或其子树void PostOrder(BinaryTreeNode*root);/按层次周游二叉树或其子树void LevelOrder(BinaryTreeNode*root);/删除二叉树或其子树void DeleteBinaryTree(BinaryTreeNode*root);,北京大学信息学院 版权所有,转载或翻印必究 Page 26,4.4 周游二叉树,周游系统地访问数据结构中的结点。每个结点都正好被访
14、问到一次。周游一棵二叉树的过程实际上就是把二叉树的结点放入一个线性序列的过程,或者说把二叉树进行线性化,北京大学信息学院 版权所有,转载或翻印必究 Page 27,4.4 周游二叉树,二叉树周游4.4.1 深度优先周游二叉树4.4.2 非递归深度优先周游二叉树4.4.3 广度优先周游二叉树,北京大学信息学院 版权所有,转载或翻印必究 Page 28,深度优先周游二叉树,我们变换一下根结点的周游顺序,可以得到以下三种方案:前序周游(tLR次序):访问根结点;前 序周游左子树;前序周游右子树。中序周游(LtR次序):中序周游左子 树;访问根结点;中序周游右子树。后序周游(LRt次序):后序周游左子
15、 树;后序周游右子树;访问根结点。,北京大学信息学院 版权所有,转载或翻印必究 Page 29,深度优先周游二叉树,深度周游如下二叉树,北京大学信息学院 版权所有,转载或翻印必究 Page 30,深度优先周游二叉树,深度周游二叉树结果 前序周游:ABDCEGFHI 中序周游:DBAEGCHFI 后序周游:DBGEHIFCA,北京大学信息学院 版权所有,转载或翻印必究 Page 31,深度优先周游二叉树(递归实现),templatevoid BinaryTree:DepthOrder(BinaryTreeNode*root)if(root!=NULL)Visit(root);/前序DepthOr
16、der(root-leftchild();/访问左子树Visit(root);/中序DepthOrder(root-rightchild();/访问右子树Visit(root);/后序,北京大学信息学院 版权所有,转载或翻印必究 Page 32,非递归深度优先周游二叉树,栈是实现递归的最常用的结构深度优先二叉树周游是递归定义的利用一个栈来记下尚待周游的结点或子树,以备以后访问。,北京大学信息学院 版权所有,转载或翻印必究 Page 33,非递归前序周游二叉树,思想:遇到一个结点,就访问该结点,并把此结点推入栈中,然后下降去周游它的左子树;周游完它的左子树后,从栈顶托出这个结点,并按照它的右链接
17、指示的地址再去周游该结点的右子树结构。template void BinaryTree:PreOrderWithoutRecusion(BinaryTreeNode*root)/非递归前序遍历二叉树或其子树,北京大学信息学院 版权所有,转载或翻印必究 Page 34,非递归前序周游二叉树,using std:stack;/使用STL中的stackstack*aStack;BinaryTreeNode*pointer=root;while(!aStack.empty()|pointer)if(pointer)/访问当前结点 Visit(pointer-value();/当前结点地址入栈 aSta
18、ck.push(pointer);,北京大学信息学院 版权所有,转载或翻印必究 Page 35,非递归前序周游二叉树,/当前链接结构指向左孩子pointer=pointer-leftchild();else/左子树访问完毕,转向访问右子树 pointer=aStack.top();aStack.pop();/栈顶元素退栈/当前链接结构指向右孩子 pointer=pointer-rightchild();/end while,北京大学信息学院 版权所有,转载或翻印必究 Page 36,非递归中序周游二叉树,思想:遇到一个结点,就把它推入栈中,并去周游它的左子树周游完左子树后,从栈顶托出这个结点并
19、访问之,然后按照它的右链接指示的地址再去周游该结点的右子树。template void BinaryTree:InOrderWithoutRecusion(BinaryTreeNode*root)/非递归中序遍历二叉树或其子树,北京大学信息学院 版权所有,转载或翻印必究 Page 37,非递归中序周游二叉树,using std:stack;/使用STL中的stackstack*aStack;BinaryTreeNode*pointer=root;while(!aStack.empty()|pointer)if(pointer)/当前结点地址入栈 aStack.push(pointer);/当前
20、链接结构指向左孩子 pointer=pointer-leftchild();,北京大学信息学院 版权所有,转载或翻印必究 Page 38,非递归中序周游二叉树,/end if else/左子树访问完毕,转向访问右子树 pointer=aStack.top();Visit(pointer-value();/访问当前结点/当前链接结构指向右孩子 pointer=pointer-rightchild();aStack.pop();/栈顶元素退栈/end else/end while,北京大学信息学院 版权所有,转载或翻印必究 Page 39,非递归后序周游二叉树,思想:遇到一个结点,把它推入栈中,周
21、游它的左子树周游结束后,还不能马上访问处于栈顶的该结点,而是要再按照它的右链接结构指示的地址去周游该结点的右子树周游遍右子树后才能从栈顶托出该结点并访问之,北京大学信息学院 版权所有,转载或翻印必究 Page 40,非递归后序周游二叉树,解决方案:需要给栈中的每个元素加上一个特征位,以便当从栈顶托出一个结点时区别是从栈顶元素左边回来的(则要继续周游右子树),还是从右边回来的(该结点的左、右子树均已周游)特征为Left表示已进入该结点的左子树,将从左边回来;特征为Right表示已进入该结点的右子树,将从右边回来,北京大学信息学院 版权所有,转载或翻印必究 Page 41,非递归后序周游二叉树,栈
22、中的元素类型定义StackElement enum TagsLeft,Right;/特征标识定义template class StackElement/栈元素的定义public:/指向二叉树结点的链接BinaryTreeNode*pointer;/特征标识申明Tags tag;,北京大学信息学院 版权所有,转载或翻印必究 Page 42,非递归后序周游二叉树,templatevoid BinaryTree:PostOrderWithoutRecusion(BinaryTreeNode*root)/非递归后序遍历二叉树或其子树using std:stack;/使用STL栈部分StackEleme
23、nt element;stack aStack;/栈申明BinaryTreeNode*pointer;if(root=NULL)return;/空树即返回,北京大学信息学院 版权所有,转载或翻印必究 Page 43,非递归后序周游二叉树,/else pointer=root;while(true)/进入左子树 while(pointer!=NULL)element.pointer=pointer;element.tag=Left;aStack.push(element);/沿左子树方向向下周游pointer=pointer-leftchild();/托出栈顶元素 element=aStack.
24、top();,北京大学信息学院 版权所有,转载或翻印必究 Page 44,非递归后序周游二叉树,aStack.pop();pointer=element.pointer;/从右子树回来while(element.tag=Right)Visit(pointer-value();/访问当前结点 if(aStack.empty()return;/else element=aStack.top();,北京大学信息学院 版权所有,转载或翻印必究 Page 45,非递归后序周游二叉树,aStack.pop();/弹栈 pointer=element.pointer;/end else/end while/
25、从左子树回来element.tag=Right;aStack.push(element);/转向访问右子树pointer=pointer-rightchild();/end while,北京大学信息学院 版权所有,转载或翻印必究 Page 46,问题讨论,前序周游算法是否还可以简洁一些?前序、中序、后序框架的算法通用性?例如后序框架是否支持前序、中序访问?若支持,怎么改动?非递归周游的意义?栈中存放了什么?,北京大学信息学院 版权所有,转载或翻印必究 Page 47,思考题,习题4.8:给定结点类型为BinaryTreeNode的三个指针p、q、rt,假设rt为根结点,求距离结点p和结点q最近
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 章节 二叉
链接地址:https://www.31ppt.com/p-5380567.html