博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线段树
阅读量:7029 次
发布时间:2019-06-28

本文共 1379 字,大约阅读时间需要 4 分钟。

线段树概述

        线段树是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶节点。
        线段树是建立在线段的基础上,每个结点都代表了一条线段[a , b]。长度为1的线段称为元线段。非元线段都有两个子结点,左结点代表的线段为[a , (a + b ) / 2],右结点代表的线段为[( a + b ) / 2 + 1 , b]。
        它的优势在于可以基本保证每个操作的复杂度为O(lgn).
        上图是一个非常简单的线段树。

基本操作

        一棵线段树一般要支持三种操作:建树(build)、查询(search)和更新(update)。

建树

        让根节点表示区间[0,N-1],即所有N个数所组成的一个区间。然后,把区间分成两半,分别由左右子树表示。不难证明,这样的线段树的节点数只有2N-1个,是O(N)级别的。
        线段树的结构如下:
struct node     {	/* data */	int left, right, mid;	//其它数据     };
        其它的节点信息根据应用情况而定。
        显然,线段树的构造是一个递归过程:
void makeTree(int start, int end, int c)     {	tree[c].left = start;	tree[c].right = end;	tree[c].mid = ((start+end)>>1);	tree[c].max = 0;	if (start == end)	{		//其它操作		return;	}	makeTree(start, tree[c].mid, (c << 1));	makeTree(tree[c].mid+1, end, (c << 1) | 1);	//其他操作     }

查询

        查询操作也是一个递归过程。对一个节点的查询要通过综合其左右子节点的查询结果。
void search(int start, int end, int c){	if (tree[c].left==start && tree[c].right==end)	{		//其它操作		return ;	}	if (start > tree[c].mid)		search(start, end, (c<<1)|1);	else if (end <= tree[c].mid)		search(start, end, c<<1);	else	{		search(start, tree[c].mid, c<<1);		search(tree[c].mid+1, end, (c<<1)|1);	}}

更新

        当用户修改一个区间的值时,如果连同其子孙全部修改,则改动的节点数必定会远远超过O(log n)个。因而,如果要想把区间修改操作也控制在O(log n)的时间内,只修改O(log n)个节点的信息就成为必要。
        借鉴前一节区间查询用到的思路:区间修改时如果修改了一个节点所表示的区间,也不用去修改它的儿子节点。然而,对于被修改节点的祖先节点,也必须更新它所记录的值,否则查询操作就肯定会出问题。
        解决方案是Lazy思想:对整个结点进行的操作,先在结点上做标记,而并非真正执行,直到根据查询操作的需要分成两部分。

应用场景

        (1):连续区间和;
        (2):区间覆盖问题;
          ……
           

 

你可能感兴趣的文章
二叉树的python可视化和常用操作代码
查看>>
http返回码
查看>>
Visual Studio 2017启动x86的Android模拟器失败
查看>>
webpack 引入jquery和第三方jquery插件
查看>>
CountDownTimer的用法及原理
查看>>
脚本中export不起作用的原因分析
查看>>
flexbox布局
查看>>
Python 元组 tuple() 方法
查看>>
P1624 单词缩写
查看>>
异常检测概览——孤立森林 效果是最好的
查看>>
laya的UI编辑器
查看>>
结构体定义变量的三种方法
查看>>
k8s相关文档
查看>>
程序崩溃原因总结
查看>>
向今天要结果; 向明天要动力 eclipse不自动弹出提示(alt+/快捷键失效)
查看>>
在PowerShell脚本中集成Microsoft Graph
查看>>
[.NET领域驱动设计实战系列]专题一:前期准备之EF CodeFirst
查看>>
函数 devm_kzalloc()【转】
查看>>
Java 多线程编程
查看>>
HBase常用Shell命令
查看>>