您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 市场营销 > 西北大学:数据结构第6章 树和二叉树
第6章树和二叉树6.1树的概念与定义6.2二叉树6.3二叉树的遍历与线索化6.4树、森林和二叉树的关系6.5哈夫曼树及其应用6.6树的计数返回主目录6.1树的概念与定义树是n(n≥0)个结点的有限集合T。当n=0时,称为空树;当n0时,该集合满足如下条件:(1)其中必有一个称为根(root)的特定结点,它没有直接前驱,但有零个或多个直接后继。(2)其余n-1个结点可以划分成m(m≥0)个互不相交的有限集T1,T2,T3,…,Tm,其中Ti又是一棵树,称为根root的子树。每棵子树的根结点有且仅有一个直接前驱,但有零个或多个直接后继。返回主目录例如:一棵树的逻辑结构图为:ABCDGFEHIJKLM从图中可以看出它好象一棵倒栽的树。返回主目录有关树的一些术语:结点:包含一个数据元素及若干指向其它结点的分支信息。结点的度:一个结点的子树个数称为此结点的度。叶结点:度为0的结点,即无后继的结点,也称为终端结点。分支结点:度不为0的结点,也称为非终端结点。孩子结点:一个结点的直接后继称为该结点的孩子结点。如上图的B、C是A的孩子。双亲结点:一个结点的直接前驱称为该结点的双亲结点。上图中A是B、C的双亲。兄弟结点:同一双亲结点的孩子结点之间互称兄弟结点。上图中的结点H、I、J互为兄弟结点。祖先结点:一个结点的祖先结点是指从根结点到该结点的路径上的所有结点。如结点K的祖先结点是A、B、E。子孙结点:一个结点的直接后继和间接后继称为该结点的子孙结点。如结点D的子孙是H、I、J、M。树的度:树中所有结点的度的最大值。结点的层次:从根结点开始定义,根结点的层次为1,根的直接后继的层次为2,依此类推。树的高度(深度):树中所有结点的层次的最大值。有序树:在树T中,如果各子树Ti之间是有先后次序的,则称为有序树。森林:m(m≥0)棵互不相交的树的集合。将一棵非空树的根结点删去,树就变成一个森林;反之,给森林增加一个统一的根结点,森林就变成一棵树。返回主目录树的抽象数据类型定义:数据对象D:一个集合,该集合中的所有元素具有相同的特性。数据关系R:若D为空集,则为空树。若D中仅含有一个数据元素,则R为空集,否则R={H},H是如下的二元关系:(1)在D中存在唯一的称为根的数据元素root,它在关系H下没有前驱。(2)除root以外,D中每个结点在关系H下都有且仅有一个前驱。返回主目录基本操作:(1)InitTree(Tree):将Tree初始化为一棵空树。(2)DestoryTree(Tree):销毁树Tree。(3)CreateTree(Tree):创建树Tree。(4)TreeEmpty(Tree):若Tree为空,则返回TRUE,否则返回FALSE。(5)Root(Tree):返回树Tree的根。(6)Parent(Tree,x):树Tree存在,x是Tree中的某个结点。若x为非根结点,则返回它的双亲,否则返回“空”。返回主目录(7)FirstChild(Tree,x):树Tree存在,x是Tree中的某个结点。若x为非叶子结点,则返回它的第一个孩子结点,否则返回“空”。(8)NextSibling(Tree,x):树Tree存在,x是Tree中的某个结点。若x不是其双亲的最后一个孩子结点,则返回x后面的下一个兄弟结点,否则返回“空”。(9)InsertChild(Tree,p,Child):树Tree存在,p指向Tree中某个结点,非空树Child与Tree不相交。将Child插入Tree中,做p所指向结点的子树。基本操作:返回主目录基本操作:(10)DeleteChild(Tree,p,i):树Tree存在,p指向Tree中某个结点,1≤i≤d,d为p所指向结点的度。删除Tree中p所指向结点的第i棵子树。(11)TraverseTree(Tree,Visit()):树Tree存在,Visit()是对结点进行访问的函数。按照某种次序对树Tree的每个结点调用Visit()函数访问一次且最多一次。若Visit()失败,则操作失败。返回主目录6.2二叉数6.2.1二叉树的定义与基本操作6.2.2二叉树的性质6.2.3二叉树的存储结构返回主目录6.2.1二叉树的定义与基本操作定义:我们把满足以下两个条件的树型结构叫做二叉树(BinaryTree):(1)每个结点的度都不大于2;(2)每个结点的孩子结点次序不能任意颠倒。下面给出二叉树的五种基本形态:(a)空二叉数(c)只有左子树的二叉树(b)只有根结点的二叉树(d)左右子树均非空的二叉树(e)只有右子树的二叉树返回主目录二叉树的基本操作:(1)Initiate(bt):将bt初始化为空二叉树。(2)Create(bt):创建一棵非空二叉树bt。(3)Destory(bt):销毁二叉树bt。(4)Empty(bt):若bt为空,则返回TRUE,否则返回FALSE。(5)Root(bt):求二叉树bt的根结点。若bt为空二叉树,则函数返回“空”。(6)Parent(bt,x):求双亲函数。求二叉树bt中结点x的双亲结点。若结点x是二叉树的根结点或二叉树bt中无结点x,则返回“空”。返回主目录基本操作:(7)LeftChild(bt,x):求左孩子。若结点x为叶子结点或x不在bt中,则返回“空”。(8)RightChild(bt,x):求右孩子。若结点x为叶子结点或x不在bt中,则返回“空”。(9)Traverse(bt):遍历操作。按某个次序依次访问二叉树中每个结点一次且仅一次。(10)Clear(bt):清除操作。将二叉树bt置为空树。返回主目录6.2.2二叉树的性质性质1:在二叉树的第i层上至多有2i-1个结点(i≥1)。当i=1时,整个二叉树只有一根结点,此时2i-1=20=1,结论成立。证明:假设i=k时结论成立,即第k层上结点总数最多为2k-1个。现证明当i=k+1时,结论成立:因为二叉树中每个结点的度最大为2,则第k+1层的结点总数最多为第k层上结点最大数的2倍,即2×2k-1=2(k+1)-1,故结论成立。返回主目录性质2:深度为k的二叉树至多有2k-1个结点(k≥1)。证明:因为深度为k的二叉树,其结点总数的最大值是将二叉树每层上结点的最大值相加,所以深度为k的二叉树的结点总数至多为:第i层上的最大结点个数=2i-1=2k-1i=1ki=1k故结论成立。返回主目录性质3:对任意一棵二叉树T,若终端结点数为n0,而其度数为2的结点数为n2,则n0=n2+1。证明:设二叉树中结点总数为n,n1为二叉树中度为1的结点总数。因为二叉树中所有结点的度小于等于2,所以有n=n0+n1+n2设二叉树中分支数目为B,因为除根结点外,每个结点均对应一个进入它的分支,所以有:n=B+1。又因为二叉树中的分支都是由度为1和度为2的结点发出,所以分支数目为:B=n1+2n2整理上述两式可得到:n=B+1=n1+2n2+1将n=n0+n1+n2代入上式得出n0+n1+n2=n1+2n2+1,整理后得n0=n2+1,故结论成立。返回主目录两种特殊的二叉树:满二叉树:深度为k且有2k-1个结点的二叉树。在满二叉树中,每层结点都是满的,即每层结点都具有最大结点数。123456789101112131415满二叉树返回主目录完全二叉树:1234567891011121314关系:满二叉树必为完全二叉树,而完全二叉树不一定是满二叉树。返回主目录性质4:具有n个结点的完全二叉树的深度为㏒2n+1。证明:设n个结点的完全二叉树的深度为k,根据性质2可知,k-1层满二叉树的结点总数为:2k-1-1k层满二叉树的结点总数为:2k-1显然有:2k-1-1n2k-12k-1n2k取对数有:k-1log2nk因为k是整数,所以k-1=log2n,k=㏒2n+1结论成立。返回主目录性质5:对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对二叉树中的所有结点从1开始顺序编号,则对于任意的序号为i的结点有:(1)若i=1,则i无双亲结点若i1,则i的双亲结点为i/2(2)若2*in,则i无左孩子若2*i≤n,则i结点的左孩子结点为2*i(3)若2*i+1n,则i无右孩子若2*i+1≤n,则i的右孩子结点为2*i+1用归纳法证明其中的(2)和(3)。返回主目录6.2.3二叉树的存储结构二叉树的结构是非线性的,每一结点最多可有两个后继。二叉树的存储结构有两种:顺序存储结构和链式存储结构。返回主目录顺序存储结构:是用一组连续的存储单元来存放二叉树的数据元素。ABCDEFGHIJKLABCDEFGHIJKL二叉树的顺序存储结构返回主目录对于一般的二叉树,我们必须按照完全二叉树的形式来存储,就会造成空间的浪费。单支树就是一个极端情况。ABCDA^B^^^C^^^^^^^D单支树返回主目录2.链式存储结构对于任意的二叉树来说,每个结点只有两个孩子,一个双亲结点。我们可以设计每个结点至少包括三个域:数据域、左孩子域和右孩子域:LChildDataRChild二叉链表DABCEFGABCDEFG二叉树T二叉链表返回主目录有时,为了找到父结点,可以增加一个Parent域,Parent域指向该结点的父结点。该结点结构如下:RChildParentDataLChild三叉链表typedefstructNode{DataTypedata;strctNode*LChild;structNode*RChild;}BiTNode,*BiTree;二叉树的二叉链表结点的结构用C语言描述为:返回主目录结论:若一个二叉树含有n个结点,则它的二叉链表中必含有2n个指针域,其中必有n+1个空的链域。证明结论:分支数目B=n-1,即非空的链域有n-1个,故空链域有2n-(n-1)=n+1个。返回主目录6.3二叉树的遍历与线索化二叉树的遍历:指按一定规律对二叉树中的每个结点进行访问且仅访问一次。二叉树的基本结构由根结点、左子树和右子树组成RChildDataLChildDataLChildLChildRChild如图示返回主目录用L、D、R分别表示遍历左子树、访问根结点、遍历右子树,那么对二叉树的遍历顺序就可以有:(1)访问根,遍历左子树,遍历右子树(记做DLR)。(2)访问根,遍历右子树,遍历左子树(记做DRL)。(3)遍历左子树,访问根,遍历右子树(记做LDR)。(4)遍历左子树,遍历右子树,访问根(记做LRD)。(5)遍历右子树,访问根,遍历左子树(记做RDL)。(6)遍历右子树,遍历左子树,访问根(记做RLD)。返回主目录在以上六种遍历方式中,如果我们规定按先左后右的顺序,那么就只剩有DLR、LDR和LRD三种。根据对根的访问先后顺序不同,分别称DLR为先序遍历或先根遍历;LDR为中序遍历(对称遍历);LRD为后序遍历。注意:先序、中序、后序遍历是递归定义的,即在其子树中亦按上述规律进行遍历。返回主目录三种遍历方法的递归定义:先序遍历(DLR)操作过程:若二叉树为空,则空操作,否则依次执行如下操作:(1)访问根结点;(2)按先序遍历左子树;(3)按先序遍历右子树。返回主目录若二叉树为空,则空操作,否则依次执行如下操作:(1)按中序遍历左子树;(2)访问根结点;(3)按中序遍历右子树。中序遍历(LDR)操作过程返回主目录后序遍历(LRD)操作过程:若二叉树为空,则空操作,否则依次执行如下操作:(1)按后序遍历左子树;(2)按后序遍历右子树;(3)访问根结点。返回主目录对于如下图的二叉树,其先序、中序、后序遍历的序列为:先序遍历:A、B、D、F、G、C、E、H。中序遍历:B、F、D、G、A、C、E、H。后序遍历:F、G、D、B、H、E、C、A。ABCDFGEH返回主目录以二叉链表作为存储结构,讨论二叉树的遍历算法1)先序遍历voidPreOrder(BiTreeroot)/*先序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/{if(root!=NULL){Visit(root-d
本文标题:西北大学:数据结构第6章 树和二叉树
链接地址:https://www.777doc.com/doc-3856548 .html