欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    树的相关知识.ppt

    • 资源ID:2405034       资源大小:1.24MB        全文页数:84页
    • 资源格式: PPT        下载积分:8金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要8金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    树的相关知识.ppt

    树的相关知识,雅礼 朱全民,红楼梦贾府关系结构示意图,树,树的定义:树是具有以下性质的有限结点集合:(1)有一个被称为“根”的结点。(2)根的所有孩子都是一颗子树的根。,树的相关术语,结点的度(degree):该结点拥有的子数数目。右图中:degree(A)=3,degree(F)=0叶子(leaf):度为0的结点双亲(parent):拥有子树的结点孩子(child):某个双亲结点的子树的根兄弟(sibling):拥有同一个双亲结点的孩子祖先(ancestor):从某一个结点往上一直到根经过的所有结点后代(descendants):子树的所有结点层次(level):双亲的层次+1;根的层次=1.高度(height)/深度(depth):max levels.,树的表示(列表表示法),(A),(A(B,C,D),(A(B(E,F),C(G),D(H,I,J),(A(B(E(K,L),F),C(G),D(H(M),I,J),树的结点的大小将会随着其子树的数目不同而变化,这对我们来说显然不是一个很好的方法。,树的表示(双亲表示法),双亲表示法 type tnode=record data:datatype;parent:integer;end;,每个结点都指向它的双亲,可以很方便从叶子找到祖先,但不能从根结点往下找。,树的表示(孩子兄弟表示法),二叉树,二叉树是度不超过2的树二叉树的特性:第 i 层的最大结点数为2i1,高度为k的二叉树的最大结点数为2k1,二叉树的表示(数组表示法),对于用数组表示的完全二叉树,对于任意结点i,有:,二叉树的表示(孩子表示法),常用的存储结构 type bitree=node node=record data:datatype;lchild,rchild:bitree;end;,二叉树的遍历,遍历(先序遍历,中序遍历,后序遍历)Proc preorder(bt:bitree);if btNil then visit(bt)preorder(bt.lchild);preorder(bt.rchild);endP,二叉树的性质,在二叉树的第i层上最多有2i-1个结点深度为K的二叉树最多有2k-1个结点在二叉树中,叶子结点的总数总比为度数为2的结点多1有n个结点的完全二叉树的结点按层序编号,则对任意一结点i,有(1)如果i=1,则结点i是二查树的根,无双亲;如果i1,则双亲是i/2(2)如果2in,则结点i无左孩子,否则左孩子为2i(3)如果2i+1n,则结点i无右孩子,否则右孩子为2i+1,树与二叉树的转换,任意一棵树的孩子兄弟表示法都有唯一对应的一颗二叉树,根结点的右孩子总是为空,森林转化为二叉树,用“孩子兄弟表示法”可以将任意一棵树转化为二叉树的形式 森林转化为二叉树 如果F=T1,T2,Tm是森林,则可按如下规则转化为一棵二叉树。1)若F为空,即m=0,则B为空树 2)若F非空,即m0,则B的根root即为森林中第一棵树的根root(T1),B的左子树为从T1中子树森林F1=T11,T12,T1i转换而成的二叉树;其右子树Rb 是从森林F=T2,Tm中转换出来的二叉树,二叉排序树(Binary Sort Tree),二叉排序树又称为二叉查找(搜索)树(BST)它或者是一颗空树,或者是具有如下性质的二叉树:1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值3)它左右子树分别为二叉排序树。,BST的特点,(1)二叉排序树中任一结点x,其左(右)子树中任一结点y(若存在)的关键字必小(大)于x的关键字。(2)二叉排序树中,各结点关键字是惟一的。实际应用中,不能保证被查找的数据集中各元素的关键字互不相同,所以可将二叉排序树定义中BST性质(1)里的小于改为大于等于,或将BST性质(2)里的大于改为小于等于,甚至可同时修改这两个性质。(3)按中序遍历该树所得到的中序序列是一个递增有序序列。,二叉排序树,在二叉树中,边有两种:红边:表示是父亲的左儿子蓝边:表示是父亲的右儿子,实例,BST的查找,FUNC bstsrch(t:bitreptr;K:keytype):bitree if(t=nil)or(t.key=K)then return(t)else if t.keyK then return(bstsrch(t.lchild,k)else return(bstsrch(t.rchild,k)endF,BST的插入,在二叉排序树中插入新结点,要保证插入后仍满足BST性质。其插入过程是:(a)若二叉排序树T为空,则为待插入的关键字key申请一个新结点,并令其为根;(b)若二叉排序树T不为空,则将key和根的关键字比较:(i)二者相等,则说明树中已有此关键字key,无须插入。(ii)keyTkey,则将它插入根的右子树中。子树中的插入过程与上述的树中插入过程相同。如此进行下去,直到将key作为一个新的叶结点的关键字插入到二叉排序树中,或者直到发现树中已有此关键字为止。,BST插入的递归算法,PROC ins_bstree(var bst:bitree;k:keytp);采用链式存储结构 begin new(s);s.key:=k;s.lchild:=nil;s.rchild:=nil;if bst=nil then bst:=s;else if Kfkey then f.lchild:=s;else f.rchild:=send;,BST的生成为进行不断插入的过程!但在生成BST的时候,可能会由于根结点选择不好,使得树很斜,查找的效率降低,可以使用随机产生根结点的方法,使得BST较平衡,下图就是两棵关键字相同的BST树.,删除,分三种情况讨论1)删除叶子节点不破坏树的结构,修改其双亲结点:f.lchild:=NIL2)若只有左孩子Pl或者只有右孩子Pr,则只要令Pl或Pr直接为f的左孩子即可:f.lchild:=P.lchild;或者f.lchild:=P.rchild;3)左右孩子都有,设中序遍历的序列为ClC.QlQSlSPPrF,令P的左孩子为f的右孩子,而P的右孩子为S的右孩子 q:=p;s:=p.lchild;while srchildnil do q:=s;s:=s.rchild p.data:=s.data;if qp then q.rchild:=s.lchild else q.lchild:=s.lchild dispose(s),练习,写一个程序,读入n个整数,构建二叉排序树,输出二叉排序树的中序遍历结果。n=100000,样例,7-表示有7个数3265741,二叉查找树时间复杂度分析,二叉查找树(Binary Search Tree)可以被用来表示有序集合、建立索引或优先队列等。最坏情况下,作用于二叉查找树上的基本操作的时间复杂度,可能达到O(n)。某些二叉查找树的变形,基本操作在最坏情况下性能依然很好,如红黑树、AVL树等。,Splay 树,Splay树是二叉查找树的改进。对Splay树的操作的均摊复杂度是O(log2n)。Splay树与二叉查找树一样,也具有有序性。即Splay树中的每一个节点x都满足:该节点左子树中的每一个元素都小于x,而其右子树中的每一个元素都大于x。Splay树的核心思想就是通过Splay操作进行自我调整,从而获得平摊较低的时间复杂度。,Splay操作,Splay操作是在保持Splay树有序性的前提下,通过一系列旋转操作将树中的元素x调整至树的根部的操作(Zig:右旋,Zag:左旋)。在旋转的过程中,要分三种情况分别处理:1)Zig 或 Zag 2)Zig-Zig 或 Zag-Zag 3)Zig-Zag 或 Zag-Zig,Splay操作 情况1,Zig或Zag操作:节点x的父节点y是根节点。,Splay操作 情况2,Zig-Zig或Zag-Zag操作:节点x的父节点y不是根节点,且x与y同时是各自父节点的左孩子或者同时是各自父节点的右孩子。,Spaly操作 情况3,Zig-Zag或Zag-Zig操作:节点x的父节点y不是根节点,x与y中一个是其父节点的左孩子而另一个是其父节点的右孩子。,Splay操作举例,Splay(1,S),Spaly树基本操作,查找:与二叉排序树查找类似,只是查找结束后要将找到的元素通过Splay操作旋转到根。插入:用查找过程找到要插入的位置,进行插入。然后将新元素旋转到根。删除:首先在树中找到要删除的元素,将他转到根节点并删去,这样原来的树就分裂成了两棵树,然后将左子树中拥有最大关键字的那一个元素转到根,由于它是左子树中的最大元素,所以他不存在有儿子,这样只要把原来的右子树作为他的右子树,就重新合并成了一棵树。可见在Splay树的基本操作中,处处要用到Splay旋转操作!,应用:Pet,宠物收养场提供两种服务:收养被离弃的宠物与让新的主人领养宠物。每个宠物有不相同的特点值。领养人所希望的特点值也不相同。如果领养人/遗弃宠物过多,则当前来的宠物/领养人选择离其特点值最近的(如果有两个特点值与其同样接近,则选择较小的)领养人/宠物,被领养/领养。并且纪录两个特点值的差值。输入N条请求(X,Y),X=0表示宠物;X=1表示领养人,Y为特征值。任务是计算所有差值的和。(N=80000,等待的宠物/领养者数M=10000),字典树(trie),当关键字是串的时候,往往用trie。我们的动机是:利用串的公共前缀来节约内存,加快检索速度。例如,需要保存“computer”和“command”,由于它们的前三个字母是相同的,所以希望它们共享前三个字母,而只有剩下部分才进行分开储存。,例如,需要保存以下8个单词:becausebeforebegbeggarbelongbelowdaydead,Trie的特点,根节点不包含字母,除根节点外每一个节点都仅包含一个英文字母从根节点到某一节点,路径上经过的字母依次连起来所构成的字母序列,称为该节点对应的单词。每个节点的所有儿子包含的字母都不相同。插入和删除的时间均为O(L)L为字符串的长度,应用:最长前缀,给定n个字符串,即基元给定一个字符串T,即生物体的结构要找出字符串T由基元构成的前缀,使得该前缀的长度最大N=100,Len(T)=500000,基元长度L=20,样例基元:A,AB,BBC,CA,BA T:ABABACABAABCB最长前缀构成有三种方法 A+BA+BA+CA+BA+AB AB+AB+A+CA+BA+AB AB+A+BA+CA+BA+AB长度为11,分析,为了尽快的查找到基元,我们把基元构成一个单词树,也叫trie树。如下图为样例的单词树。该树最多为26叉树,任何单词要么是某个单词的前缀,要么为从根到叶子结点组成的单词。这样我们只需要O(L)的时间即可查找到某个单词,L为单词的长度。,动态规划,我们设前j个字符已经匹配,考虑前i个字符是否能匹配,主要看从i+1j组成的字符串是否是单词因此设f(i)表示前i个字符是否已匹配,若能匹配则为真(用1表示),否则为假(用0表示)。则有:,时间复杂度分析,每次求f(i)需要向前找f(j),i-jL,每移动一次j需要判定word(j+1,i)是否是单词1=i=len(T),1=i-jL查找单词时间复杂度为O(L)因此总时间复杂度为O(len(T)*L2)。因为T=500000,L=20,因此,5*105*202=2*108,并查集引例,写一个数据结构,支持一下两种操作:现有若干个队伍,1、询问两个人是否属于同一个队伍2、合并两个人所在的队伍,输入样例,第一行 n m 表示有n个人(用1到n表示),在开始时没有两个人是属于同一个队伍。接下来m行,表示m次操作。每行操作有2种可能:1 x y 表示询问x和y是不是在同一个队伍2 x y 合并x和y所在的队伍(如果x和y已经在同一队伍,不做任何操作),样例,4 51 1 32 1 31 1 32 3 41 4 1n=100000m=100000,NOYESYES,分析,每个队伍实际上是一个集合,两个操作相当于:1、询问两个元素是否在同一个集合2、合并两个集合尝试用树结构表示一个集合A与B是父子关系表示A与B 在同一个队伍,问题一,如何知道两个节点是否在同一颗树中?,问题二,怎样合并两颗树?,用双亲表示法存储树结构,若两种操作都解决了,如何储存这颗树呢?n-表示一共n个节点father1,father2,fathern表示每个节点的父亲节点是谁。如果t为根,则fathert=0,如何寻找根节点?,function find(t:longint):longint;var f:longint;begin f:=t;while fatherf0 do f:=fatherf;find:=f;end;,int find(int t)int f;f=t;while(fatherf!=0)f=fatherf;return(f);,启发式合并,如何合并?,procedure unionxy(x,y:longint);begin x:=find(x);y:=find(y);if xy then fatherx:=y;end;,voidunionxy(int x,int y)x=find(x);y=find(y);if(x!=y)fatherx=y;return;,效率分析,不断询问红色节点所在的根节点,路径压缩!,路径压缩,f为根节点while fathert0 do begin p:=fathert;fathert:=f;t:=p;end;,f为根节点while(fathert!=0)p=fathert;fathert=f;t=p;,并查集的时间复杂度,可以证明,经过启发式合并和路径压缩之后的并查集,执行m次查找的复杂度为O(m(m)其中(m)是Ackermann函数的某个反函数,你可以近似的认为它是小于5的。所以并查集的单次查找操作的时间复杂度也几乎是常数级的。,应用1:friend,有一个镇有N个居民。当然其中有许多人是朋友的关系。根据有名的谚语:“我朋友的朋友也是我的朋友”,所以如果A和B是朋友,B和C是朋友,那么A和C也是朋友。你的任务是算出在这个镇中最大的朋友集团为多少人。【输入文件】输入文件的第一行有2个正整数 N 和 M。N代表镇上居民的数目(1=N=30000),M 代表这些居民中朋友关系的数目(0=M=30000)。接下来的M行每行有2个整数A,B(1=A,B=N,A不等于B),代表A,B为朋友关系。这M行中可能有的会重复出现。【输出文件】输出文件仅一行,在这个镇中最大的朋友集团为多少人。,应用2:银河英雄传说,银河系的两大军事集团在巴米利恩星域爆发战争。泰山压顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨威利组织麾下三万艘战舰迎敌。杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气。在这次决战中,他将巴米利恩星域战场划分成30000列,每列依次编号为1,2,30000。之后,他把自己的战舰也依次编号为1,2,30000,让第i号战舰处于第i列(i=1,2,30000),形成“一字长蛇阵”,诱敌深入。这是初始阵形。当进犯之敌到达时,杨威利会多次发布合并指令,将大部分战舰集中在某几列上,实施密集攻击。合并指令为M i j,含义为让第i号战舰所在的整个战舰队列,作为一个整体(头在前尾在后)接至第j号战舰所在的战舰队列的尾部。显然战舰队列是由处于同一列的一个或多个战舰组成的。合并指令的执行结果会使队列增大。,然而,老谋深算的莱因哈特早已在战略上取得了主动。在交战中,他可以通过庞大的情报网络随时监听杨威利的舰队调动指令。在杨威利发布指令调动舰队的同时,莱因哈特为了及时了解当前杨威利的战舰分布情况,也会发出一些询问指令:C i j。该指令意思是,询问电脑,杨威利的第i号战舰与第j号战舰当前是否在同一列中,如果在同一列中,那么它们之间布置有多少战舰。作为一个资深的高级程序设计员,你被要求编写程序分析杨威利的指令,以及回答莱因哈特的询问。,分析,由于我们要得到的信息除了某条战舰在哪个队列,还要知道它在该队列中的位置。因此需要对并查集进行扩充。定义:ai:战舰i暂时标记为属于以战舰ai为首的队列,称战舰ai为战舰i的父节点bi:战舰i到战舰ai(包括战舰ai)之间的战舰数量,称bi为战舰i到战舰ai的深度。ci:战舰i所属队列后方(包括战舰i本身)的战舰数量(注意:此变量只有当ai=i时才有意义),称ci为队列长度。,分析,初始时:ai=i,bi=0,ci=1对于每个M i j命令,需要进行如下操作:对战舰i,j进行查找和路径压缩设ai=r1,aj=r2且r1r2,则:ar1=r2,br1=cr2,cr2=cr1+cr2对于每个C i j命令,需要进行如下操作:对战舰i,j进行查找和路径压缩判断是否有ai=aj,如是则表示他们是同一队列,输出|bi-bj|-1;如果不是则输出-1,引例,写一种数据结构,完成以下3种操作:(操作的总次数不超过100000)1、插入一个数2、询问最小值3、删除最小值要求是这3种操作都要快。,输入输出,输入每行一次操作,有如下三种:1 x:表示插入X这个数2:表示询问当前最小值3:表示删除最小值输出对于每个询问最小值操作,输出一行,每行仅一个数,表示当前的最小值。,输入:9-9次操作1 2021 301 1023232,输出:20102030,样例,用线性表作为数据结构,无序表:插入操作 O(1)询问最小值 O(n)删除最小值 O(n)有序表:插入操作 O(n)询问最小值 O(1)删除最小值 O(1),二叉堆,定义堆是一棵完全二叉树,对于每一个非叶子结点,它的权值都不大于(或不小于)左右孩子的权值,我们称这样的堆为小根堆(或大根堆)。描述如下:n个元素的序列k1,k2,kn,当且仅当满足 ki=k2i 并且 ki=k2i+1 二叉堆肯定是一颗完全二叉树,在堆中插入元素x,首先将元素x放到堆中的最后一个位置(即最底层最右边的位置),然后不断地把x往上调整,直到x调不动为止(即大于它现在的父亲,或者x处于根结点)。,定义一个堆:Var st:array1.maxn of longint;/存储堆 n:longint;/堆中元素个数,插入(实际上是不断向上调整的过程),PROC up(k:longint);把第k个结点上调begin while k1 do begin i:=k div 2;i是k的父亲 if stistk then begin swap(i,k);k:=i;交换结点i和k end else exit;end;end;,在堆中删除任意一个元素,这里说指的删除任意一个元素,是指在当前堆中位置为w的元素。过程如下:首先把位置w的元素和最后一个位置的元素交换,然后删去最后一个位置,这样w上的元素就被删除了。接着把位置w上的新元素不断下调,直到满足堆的性质。,删除(实际上是不断向下调整的过程),PROC down(k:longint);把第k个结点往下调begin while k+k=n do begin i:=min 2k,2k+1;如果2k+1不存在直接返回k+k否则返回2个中间的值较小的元素 if stistk then begin swap(i,k);k:=i;end else exit end;end;,堆的构造就是不断插入到堆的过程,堆的插入.删除,PROC add(x:longint);添加一个值为x的元素begin inc(n);stn:=x;up(n)end;PROC del(x:longint);删除一个值为x的元素begin an:=ax;down(x)end;,给定m个实数w1,w2,wm,(m=2),要求一个具有m个外部节点的扩充二叉树,每个外部ki节点有一个wi与之对应,作为它的权,使得带权外部路径长度 最小,其中li是从根到外部节点的路径长度。,应用1:哈夫曼树,算法,1.构造m个只有1个节点的树2.找两个最小的权3.以这两个节点为左右儿子构造一个二叉树,并将该数的根节点权之为左右儿子权值之和4.继续第二步,直到剩下一棵树为止,应用2:任务,有n个任务,每个任务有一个截止完成的时间Ti和完成需要的时间Ci。现在你一个人希望从0时刻开始完成尽量多的任务。问最多能完成多少任务?,引例:数列操作,假设有一列数Ai(1in),支持如下两种操作:将Ak的值加D。(k,D是输入的数)输出As+As+1+At。(s,t都是输入的数,ST)输入:第一行一个整数n,第二行为n个整数,表示Ai的初始值。第三行为一个整数m,表示操作数 下接m行,每行描述一个操作,有如下两种情况:ADD k d(表示将Ak加d,1=k=n,d为整数)SUM s t(表示输出As+At)输出:对于每一个SUM提问,输出结果,如果按题目要求直接模拟:每一个ADD操作的复杂度是O(1)每一个SUM操作的复杂度是O(N)可见对于M次SUM询问,复杂度是O(NM)有没有更好的方法呢?这里我们提出一种称之为线段树的数据结构。,用队列直接模拟,线段树的定义,线段树是一棵二叉树,记为T(a,b),参数a,b表示区间a,b,其中b-a称为区间的长度,记为L。线段树T(a,b)也可递归定义为:若L1:a,(a+b)div 2为 T的左儿子;(a+b)div 2,b为T 的右儿子。若L=1:T为叶子节点。,表示区间1,10的线段树样例:,线段树的建立,我们知道,对于长度为n的线段建立的线段树,至多只有nlogn个节点,故建立线段树的复杂度是O(nlogn),Procedure MakeTree(a,b)Var Now:LongintBegin tot tot+1 Now tot TreeNow.a a TreeNow.b b If a+1 b then TreeNow.Left tot+1 MakeTree(a,)TreeNow.Right tot+1 MakeTree(,b)End,回到原问题,我们用线段树来维护序列。给线段树的每个节点增加一个域Treei.S,表示该区间内所有值的和。对于ADD k d操作,只需要从根节点开始遍历线段树中每个包含了k的区间节点,然后修改S域。由于这样的区间至多只有logn个,所以一次ADD操作的复杂度是O(logn),SUM操作,对于待计算的区间s,t:Function getsum(v):integer;if(s=Treev.a)and(Treev.b=t)then getsum:=Treev.S else begin tot:=0;if s,t和Treev.Left表示的区间相交 then tot:=tot+getsum(Treev.Left);if s,t和Treev.Right表示的区间相交 then tot:=tot+getsum(Treev.Right);getsum:=tot end;我们不难发现这个过程中所遍历到的区间数(节点数)和线段树的深度同阶,因此时间复杂度是O(logn),问题的解决,综上,M次操作的时间复杂度为O(Mlogn)通过引入线段树的数据结构,虽然ADD操作的复杂度提高到了O(logn)。但SUM操作变得更快(O(logn)。从而也使得算法在大数据处理上更加高效。,

    注意事项

    本文(树的相关知识.ppt)为本站会员(仙人指路1688)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开