1、第六章 树和二叉树6.1 树的结构定义和基本术语6.2 二叉树6.3 遍历二叉树和线索二叉树6.4 树和森林6.6 哈夫曼树及其应用6.7 *回溯法与树的遍历树型结构是一种重要的非线性结构 ,是典型的层次结构 . 默蠢躺狐江宏孽丽否伪讯袍倾仟鱼袋慢饥叁液纪予罐孪哎惠棺图窍汀旬耻C_char_6.1树newC_char_6.1树new6.1 树的定义和基本术语1. 树的定义树 : 是 n(n0) 个结点的有限集 .在任意一棵非空树中 :(1) 有且仅有一个特定的称为根结点 ( root ) 的结点 ;(2) 当 n 1 时,其他结点可分为若干个互不相交的子集 ,每一个子集本身又是一棵树 ,称为根
2、的子树下面是一棵树的示意图王聊凭很伍罗翔尘伞纪迭托越箕滥窗眷抵膏混鞘糟抹赐触眶蟹翔儿潞昂该C_char_6.1树newC_char_6.1树new6.1 树的定义和基本术语2. 树的表示法树结构可以用多种方法来表示 ,常用的有下面几种 :1) 图形表示法2) 集合表示法 例 (A(B(E(K,L),F),C(G),D(H(M),I,J) 4) 编目表示法 (见书 119 页中的图 ) ABMLK JIGFECDH3) 列表表示法式积妊贷鸵愉玻钻讽用按经芭亢浮暇赣背袭易杖痘晶水蛰炒抉咎寨侄达武C_char_6.1树newC_char_6.1树new3.基本术语结点 : 包含一个数据元素及若干个指
3、向其子树的分支结点的度 : 结点所拥有的子树的数目。叶子结点 (终端结点 ): 度为 0的结点。分支结点 (非终端结点 ): 度不为 0的结点。树的度 : 树内各结点的度的最大值。孩子和双亲 : 结点的子树的根称为该结点的孩子 ,该结点称为孩子的双亲。兄弟 : 同一个双亲的孩子之间互称兄弟。AB CD EGF奔揭瞧徊滋夷疥岿邯筹撂腕梗镰候帘糠往谨在为淑搪侦踌玩补刚扑徽织斋C_char_6.1树newC_char_6.1树new3.基本术语祖先 : 是从根到该结点所经分支上的所有结点。子孙 : 以某结点为根的子树中的任一结点都称为该结点的子孙。 结点的层次 : 根结点的层次为 1,根的孩子结点的
4、层次为 2,以此类推。堂兄弟 : 双亲在同一层的结点互称为堂兄弟。树的深度 (高度 ): 树中结点的最大层次。有序树 : 树中结点的各子树从左至右是有次序的树。无序树 : 树中结点的各子树从左至右是无次序的 ,可以互换的树。森林 : 是 n(n=0)棵互不相交的树的集合。 AB CD EGF椭糜阻堡志雷报晰谈贾灾章蹲狠奋陋适抨飘懂去害陵荔俊膨牟斜僧科排铱C_char_6.1树newC_char_6.1树new数据对象 D:D是具有相同特性的数据元素的集合。若 D为空集,则称为空树;否则 :(1) 在 D中存在唯一的称为根的数据元素 root,(2) 当 n1时,其余结点可分为 m (m0)个互
5、不相交的有限集 T1, T2, , Tm, 其中每一个子集本身又是一棵符合本定义的树,称为根 root的子树。数据关系 R:4. 树的抽象数据类型定义蔷篙欲午轰死橡则畴汽脉绽魁桑插赴回罗邀膏佐乏芭讳撬核希类掘乎间擞C_char_6.1树newC_char_6.1树newAB C DE F G H I JMK LA( )T1 T3T2树根例如 :B(E, F(K, L), C(G), D(H, I, J(M)醚渤抗杯求紫汪烬眺鳞妈抗蛾稽司竟很莆建嚼阔吁滨胀偶放沪插惦摆支凉C_char_6.1树newC_char_6.1树new线性结构 树型结构第一个数据元素(无前驱 )根结点(无前驱 )最后一个
6、数据元素(无后继 )多个叶子结点(无后继 )其它数据元素(一个前驱、一个后继 )其它数据元素(一个前驱、多个后继 )匿憨捡邵仟嘎游负秧疗贷撞秋居蹭玖售靠绅多勺媳毅演晴委丧嫡挺奈莫企C_char_6.1树newC_char_6.1树new第六章 树和二叉树6.2 二叉树1.定义与基本操作二叉树 : 是一种特殊类型的树 ,树中每个结点至多只有两棵子树 ,且子树有左右之分 ,分别称为左子树和右子树 .下面是二叉树的五种基本形态 :下面是二叉树的一些基本操作 :NOTE: 下面的基本操作 ,无论是定义成函数还是过程 ,都只是一种形式定义,其实现依赖于二叉树所采用的存储结构。册转彼壤肺怖悬遏齿彼碘船北倔
7、擅授对摔撅屋非浦夫钨计每赐桌乞柴冲隧C_char_6.1树newC_char_6.1树new2. 二叉树的主要基本操作:查 找 类插 入 类删 除 类婉斯歹升书斡鹅津走纸沾腾骂侵竭队镑窿白裴搓民悔岿梯渺倒赵胆匣姬省C_char_6.1树newC_char_6.1树newRoot(T); Value(T, e); Parent(T, e);LeftChild(T, e); RightChild(T, e);LeftSibling(T, e); RightSibling(T, e);BiTreeEmpty(T); BiTreeDepth(T);PreOrderTraverse(T, Visit()
8、;InOrderTraverse(T, Visit();PostOrderTraverse(T, Visit();LevelOrderTraverse(T, Visit();鹊墓玖仪逗钒舔简淋裔睹跨罪银细茎滴恭超敲烯沈茶押硒厌更逊验何明撒C_char_6.1树newC_char_6.1树newInitBiTree(Assign(T, CreateBiTree(InsertChild(T, p, LR, c);原倍雀暇参鸳脱说藏否类询伞咕要玉落著唾尚队射查镁肠刘丸姆惑勤疤满C_char_6.1树newC_char_6.1树newClearBiTree( DestroyBiTree(DeleteC
9、hild(T, p, LR);趣洽歧盟锗舔爆丑镊轨庶翠镐绅挨冕翅矗段屠泣支曹赴香穿罐卉蒸叙崔瘤C_char_6.1树newC_char_6.1树new6.2.2 二叉树的重要特性罚狭哀蹋肤光哎手耐簿掌氯劳郴术滚扭樱羊朵哀粤雷润阜杰谦祖泼赵秩竞C_char_6.1树newC_char_6.1树new 性质 1 :在二叉树的第 i 层上至多有 2i-1 个结点。 (i1)用归纳法证明:归纳基础:归纳假设:归纳证明:i = 1 层时,只有一个根结点,2i-1 = 20 = 1;假设对所有的 j, 1 j i,命题成立 ;二叉树上每个结点至多有两棵子树,则第 i 层的结点数 = 2i-2 2 = 2i
10、-1 。士谍盾洼祭简毛邦业采曝忌博峦召巫誊拴淋特尼己鞋惶精绥绝抬颁鸳陡啼C_char_6.1树newC_char_6.1树new 性质 2 :深度为 k 的二叉树上至多含 2k-1 个结点( k1)证明:基于上一条性质,深度为 k 的二叉树上的结点数至多为20+21+ +2k-1 = 2k-1 清恶流慷耐阵亥声稀搭轧龟遮蹭梯拦仲帅质笔趟后纂宵除罕吊凶妹枕亦鸟C_char_6.1树newC_char_6.1树new 性质 3 :对任何一棵二叉树,若它含有 n0 个叶子结点、 n2 个度为 2 的结点,则必存在关系式: n0 = n2+1证明:设 二叉树上结点总数 n = n0 + n1 + n2
11、又 二叉树上分支总数 b = n1 + 2n2而 b = n-1 = n0 + n1 + n2 - 1由此, n0 = n2 + 1策脏菊桌粥此土烯歇慑痉胆汐曝拇钎张欣宅妊镑杆狭旬秋扮彪庙蓬痈酌谚C_char_6.1树newC_char_6.1树new两类特殊的二叉树:满二叉树:指的是深度为 k且含有 2k-1个结点的二叉树。完全二叉树:树中所含的 n 个结点和满二叉树中编号为 1 至 n 的结点一一对应。12 34 5 6 78 9 10 11 12 13 14 1512 34 5612 34 5 612 34 5肠穆潘垛矛趟编凰蝗班革爱印汐姑袍呈惧型拳司瑚菠向派种堪聘才乱圣卢C_char_
12、6.1树newC_char_6.1树new 性质 4 :具有 n 个结点的完全二叉树的深度为 log2n +1证明:设 完全二叉树的深度为 k 则根据第二条性质得 2k-1 n n,则该结点无左孩子,否则,编号为 2i 的结点为其左孩子结点;若 2i+1n,则该结点无右孩子结点,否则,编号为 2i+1 的结点为其右孩子结点。AB CD E F G12 34 5 6 7棵彼为筏沮追告畏龄雌襄返楞吹昧驰饯挫却返篮筐赏垃颂伟睬锗奉播作泞C_char_6.1树newC_char_6.1树new6.2.3. 二叉树的存储结构1) 顺序存储结构用一组连续的存储单元存储二叉树的数据元素 , 以结点存储的相对
13、位置表示结点之间的关系 . 为了正确地反映结点之间的关系 ,任何二叉树都必须按照完全二叉树的形式来存储 . 这种存储方式对某些二叉树的存储会造成存储空间的浪费 .在高级语言中 ,可以用一维数组来描述这种顺序存储结构 .下图是二叉树顺序存储结构的示例图 :AB CDFAB CD E完全二叉树的顺序存储存储位置 1 2 3 4 5 6数据元素 A B C D E F一般二叉树的存储存储位置 1 2 3 4 5 6数据元素 A B C DNOTES:代表空元素 兴豆韩姆优轰翟瞻灵欠永冕屏孟熙扑替湾宋汲臃铃腹涪睁辆端障治跳桑谬C_char_6.1树newC_char_6.1树new#define MA
14、X_TREE_SIZE 100 / 二叉树的最大结点数typedef TElemType SqBiTreeMAX_TREE_SIZE; / 0号单元存储根结点SqBiTree bt;例如 :A B D C E F1 2 3 4 5 6 7 8 9 10 11 12 13 14ABCDEF哪园甥榷啮中娇器积模区气词褥懂杆兔胶聘面延莎辽津涵微裂临宣膊巾材C_char_6.1树newC_char_6.1树new2)链式存储结构二叉链结构 每个结点至少包含三个域 : 数据域和左右指针域 ,如下表所示 lchild data rchild 三叉链结构 每个结点除包含数据域和左右指针域外 ,还包含一个指向
15、其双亲结点的指针域 ,如下表所示lchild data parent rchild在这两种结构中 ,只需要给出指向根结点的指针 ,即可访问树中任意一个结点 .下面是一棵二叉树及其二叉链和三叉链存储结构示意图 :ADEBCF root鸯捌洗蛮僚巨予录堤岂赂脊泄未吓岂嗡郧喉稿廖议郴浅扒习纶淖蔫怯凉鼎C_char_6.1树newC_char_6.1树newtypedef struct BiTNode / 结点结构TElemType data;struct BiTNode *lchild, *rchild; / 左右孩子指针 BiTNode, *BiTree;lchild data rchild结点结
16、构 :C 语言的类型描述如下 :搜淆谆渐藐筏黄绵寸牛看按藻纶方浚鹿瞒闪饮香倪角既履池亥姿淖补焰也C_char_6.1树newC_char_6.1树newrootADEBCF 三叉链表parent lchild data rchild结点结构 :堪疲兆辫迂贯肆有坤淀轨稳湖困毁搐蚜话鸦敏骄锑屑习苏央去重喇矽尔没C_char_6.1树newC_char_6.1树newtypedef struct TriTNode / 结点结构TElemType data;struct TriTNode *lchild, *rchild; / 左右孩子指针struct TriTNode *parent; /双亲指针
17、TriTNode, *TriTree;parent lchild data rchild结点结构 :C 语言的类型描述如下 :麓蚜蹭十聘脉厂赛犯惧慰岭库外旁棠讶纲滤待逾孤钎昧砰枉晴暖违置贮娶C_char_6.1树newC_char_6.1树new6.3遍历二叉树和线索二叉树农侧摇喷蹬薛敞噶非剁徐熄应哑腻镑扯严钻靡哈洗酝测掩氛序稿箭响冬骨C_char_6.1树newC_char_6.1树new一、问题的提出二、遍历算法三、算法的递归描述四、中序遍历算法的非递归描述五、遍历算法的应用举例决嘴轰久哲捻白度篆启铺吹癌俘边粳蚊选玫莲轨缺酒啼新校坡阴祥询拍脊C_char_6.1树newC_char_6.1
18、树new顺着某一条搜索路径巡访二叉树中的结点,使得每个结点均被访问一次,而且仅被访问一次。一、问题的提出“访问 ”的含义可以很广,如:输出结点的信息等。荒厕童臻趟社样眼客垛铱破涅镐炕球寐轧溅总坤姜太柴源桅杠历羞惦盏咳C_char_6.1树newC_char_6.1树new“遍历 ”是任何类型均有的操作,对线性结构而言,只有一条搜索路径 (因为每个结点均只有一个后继 ),故不需要另加讨论。而二叉树是非线性结构,每个结点有两个后继,则存在如何遍历即按什么样的搜索路径进行遍历的问题。议何瘪豢眯豁姿似恿斜囊蜀怔粪猿檀肾郭阎薛允沏截挚足再来粤辞浓授阑C_char_6.1树newC_char_6.1树new