数据结构-讲义-线段树.ppt
《数据结构-讲义-线段树.ppt》由会员分享,可在线阅读,更多相关《数据结构-讲义-线段树.ppt(66页珍藏版)》请在三一办公上搜索。
1、线段树,线段树,在一类问题中,我们需要经常处理可以映射在一个坐标轴上的一些固定线段,例如说映射在OX轴上的线段。由于线段是可以互相覆盖的,有时需要动态地取线段的并,例如取得并区间的总长度,或者并区间的个数等等。一个线段是对应于一个区间的,因此线段树也可以叫做区间树。,线段树的构造思想,线段树是一棵二叉树,树中的每一个结点表示了一个区间a,b。每一个叶子节点表示了一个单位区间。对于每一个非叶结点所表示的结点a,b,其左儿子表示的区间为a,(a+b)/2,右儿子表示的区间为(a+b)/2,b。,线段树的运用,线段树的每个节点上往往都增加了一些其他的域。在这些域中保存了某种动态维护的信息,视不同情况
2、而定。这些域使得线段树具有极大的灵活性,可以适应不同的需求。,例1,桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如右图所示。现在从桌子的前方射来一束平行光,把盒子的影子投射到了墙上。问影子的总宽度是多少?,分析,这道题目是一个经典的模型。在这里,我们略去某些处理的步骤,直接分析重点问题,可以把题目抽象地描述如下:x轴上有若干条线段,求线段覆盖的总长度。,最直接的做法,设线段坐标范围为min,max。使用一个下标范围为min,max-1的一维数组,其中数组的第i个元素表示i,i+1的区间。数组元素初始化全部为0。对于每一条区间为a,b的线段,将a,b内所有对应的数组元素均设为1。最后统计数组
3、中1的个数即可。,示例,初始情况1,23,54,65,6,4个1,缺点,此方法的时间复杂度决定于下标范围的平方。当下标范围很大时(0,10000),此方法效率太低。,离散化的做法,基本思想:先把所有端点坐标从小到大排序,将坐标值与其序号一一对应。这样便可以将原先的坐标值转化为序号后,对其应用前一种算法,再将最后结果转化回来得解。该方法对于线段数相对较少的情况有效。,示例,10000,22000 30300,55000 44000,60000 55000,60000排序得10000,22000,30300,44000,55000,60000对应得1,2,3,4,5,6 1,2 3,5 4,6 5
4、,6,示例,初始情况1,23,54,65,6,4个1,示例,10000,22000,30300,44000,55000,600001,2,3,4,5,6(22000-10000)+(60000-30300)=41700,1 2 3 4 5 6,10000 22000 30300 44000 55000 60000,缺点,此方法的时间复杂度决定于线段数的平方。对于线段数较多的情况此方法效率太低。,使用线段树的做法,给线段树每个节点增加一个域cover。cover=1表示该结点所对应的区间被完全覆盖,cover=0表示该结点所对应的区间未被完全覆盖。,1,6,0,3,6,0,1,6,0,1,3,0
5、,3,6,0,1,2,0,2,3,0,3,4,0,4,6,0,4,5,0,5,6,0,1,3,0,1,2,1,加入1,2,加入3,5,3,4,1,4,6,0,4,5,1,1,2,1,3,4,1,4,5,1,加入4,6,4,6,1,4,6,1,程序实现,线段树的数据结构表示,1、动态数据结构2、完全二叉树,动态数据结构,typepNode=TreeNode;TreeNode=recordb,e:Integer;l,r:pNode;cover:Integer;end;,对应区间,左右孩子,5,9,完全二叉树,1,9,1,5,1,3,3,5,5,7,7,9,7,8,8,9,5,6,6,7,3,4,4
6、,5,1,2,2,3,完全二叉树,typeTreeNode=recordb,e:Integer;cover:Integer;end;,对应区间,插入算法,procedure Insert(p,a,b:Integer);var m:Integer;begin if Treep.cover=0 then begin m:=(Treep.b+Treep.e)div 2;if(a=Treep.b)and(b=Treep.e)then Treep.cover:=1 else if b=m then Insert(p*2+1,a,b)else begin Insert(p*2,a,m);Insert(p*
7、2+1,m,b);end;end;end;,取中值,未被完全覆盖,完全覆盖,在左边,在右边,二分,统计算法,function Count(p:Integer):Integer;begin if Treep.cover=1 then Count:=Treep.e Treep.b else if Treep.e Treep.b=1 then Count:=0 else Count:=Count(p*2)+Count(p*2+1);end;,被完全覆盖,是单位区间,二分递归求解,事实上,我们也可以不在每个节点中保存其表示范围,而是在递归调用时增加两个参数来加以表示。,另一种定义,typeTreeNo
8、de=record cover:Integer;end;,插入算法,procedure Insert(p,l,r,a,b:Integer);var m:Integer;begin if Treep.cover=0 then begin m:=(l+r)div 2;if(a=l)and(b=r)then Treep.cover:=1 else if b=m then Insert(p*2+1,m,r,a,b)else begin Insert(p*2,l,m,a,m);Insert(p*2+1,m,r,m,b);end;end;end;,Treep.b换成了l,Treep.e换成了r,递归时需要
9、多加两个参数,其余都一样,统计算法,function Count(p,l,r:Integer):Integer;begin if Treep.cover=1 then Count:=r-l else if r l=1 then Count:=0 else Count:=Count(p*2,l,(l+r)div 2)+Count(p*2+1,(l+r)div 2,r);end;,这个也一样,例2,桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如右图所示。问从桌子前方可以看到多少个盒子?假设人站得足够远。,Wall,分析,可以这样来看这道题:x轴上有若干条不同线段,将它们依次染上不同的颜色,问最
10、后能看到多少种不同的颜色?(后染的颜色会覆盖原先的颜色)我们可以这样规定:x轴初始是颜色0,第一条线段染颜色1,第二条线段染颜色2,以此类推。,分析,原先构造线段树的方法不再适用,但是我们可以通过修改线段树的cover域的定义,使得这道题也能用线段树来解。定义cover如下:cover=-1表示该区间由多种颜色组成。cover=0表示该区间只有一种单一的颜色cover。,插入算法,procedure Insert(p,l,r,a,b,c:Integer);var m:Integer;begin if Treep.cover c then begin m:=(l+r)div 2;if(a=l)a
11、nd(b=r)then Treep.cover:=c else begin if Treep.cover=0 then begin Treep*2.cover:=Treep.cover;,未被完全覆盖或者染色不同,为什么?有可能越界吗?,插入算法,Treep*2+1.cover:=Treep.cover;Treep.cover:=-1;end;if b=m then Insert(p*2+1,m,r,a,b,c)else begin Insert(p*2,l,m,a,m,c);Insert(p*2+1,m,r,m,b,c);end;end;end;end;,未被完全覆盖或者染色不同,为什么?有
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 讲义 线段
链接地址:https://www.31ppt.com/p-6578851.html