数据结构:线段树
发布日期:2021-06-30 11:35:51
浏览次数:2
分类:技术文章
本文共 2518 字,大约阅读时间需要 8 分钟。
已迁往:一、线段树基本概念
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树需要的空间为数组大小的四倍
二、线段树的存储数据结构
由上面的图可以看出,存储一颗线段树和二叉树有点类似,需要左孩子和右孩子节点,另外,为了存储每条线段出现的次数,所以一般会加上计数的元素,其具体如下:
struct Node // 线段树{ int left; int right; int counter;}segTree[4*BORDER];其中,;left代表 左端点、right代表右端点,counter代表每条线段出现的次数,BORDE代表线段端点坐标不超过100。由上面的性质可以知道,我们需要4倍的空间来存储。
三、线段树支持的操作
一颗线段树至少支持以下四个操作:
- void construct(int index, int lef, int rig),构建线段树 根节点开始构建区间[lef,rig]的线段树
- void insert(int index, int start, int end),插入线段[start,end]到线段树, 同时计数区间次数
- int query(int index, int x),查询点x的出现次数,从根节点开始到[x,x]叶子的这条路径中所有点计数相加方为x出现次数
- void delete_ (int c , int d, int index),从线段树中删除线段[c,d]
具体操作如下:
1、线段树的创建
/* 构建线段树 根节点开始构建区间[lef,rig]的线段树*/void construct(int index, int lef, int rig){ segTree[index].left = lef; segTree[index].right = rig; if(lef == rig) // 叶节点 { segTree[index].counter = 0; return; } int mid = (lef+rig) >> 1; construct((index<<1)+1, lef, mid); construct((index<<1)+2, mid+1, rig); segTree[index].counter = 0;}
2、线段树的元素插入
/* 插入线段[start,end]到线段树, 同时计数区间次数 */void insert(int index, int start, int end){ if(segTree[index].left == start && segTree[index].right == end) { ++segTree[index].counter; return; } int mid = (segTree[index].left + segTree[index].right) >> 1; if(end <= mid)//左子树 { insert((index<<1)+1, start, end); }else if(start > mid)//右子树 { insert((index<<1)+2, start, end); }else//分开来了 { insert((index<<1)+1, start, mid); insert((index<<1)+2, mid+1, end); }}
3、线段树的元素查找
/* 查询点x的出现次数 * 从根节点开始到[x,x]叶子的这条路径中所有点计数相加方为x出现次数 */int query(int index, int x){ if(segTree[index].left == segTree[index].right) // 走到叶子,返回 { return segTree[index].counter; } int mid = (segTree[index].left+segTree[index].right) >> 1; if(x <= mid) { return segTree[index].counter + query((index<<1)+1,x); } return segTree[index].counter + query((index<<1)+2,x);}
4、线段树的元素删除
void delete_ (int c , int d, int index){ if(c <= segTree[index].left && d >= segTree[index].right) segTree[index].counter--; else { if(c < (segTree[index].left + segTree[index].right)/2 ) delete_( c,d, segTree[index].left); if(d > (segTree[index].left + segTree[index].right)/2 ) delete_( c,d, segTree[index].right); }}
四、线段树的应用
- 区间最值查询问题
- 连续区间修改或者单节点更新的动态查询问题
- 多维空间的动态查询
转载地址:https://iteblog.blog.csdn.net/article/details/8219727 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2024年04月23日 10时44分19秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
基于Java的截图工具
2019-04-30
基于JAVA的停车场管理系统
2019-04-30
基于Java实现的商品推荐系统
2019-04-30
基于Jsp和MySql实现的网络聊天室
2019-04-30
基于JSP心悦图书城系统设计与实现
2019-04-30
基于Spring+SpringMVC+hibernate实现的体检中心管理系统
2019-04-30
基于JAVA的宠物网站的设计与实现
2019-04-30
基于JSP的SSM框架实现的员工信息管理系统
2019-04-30
基于Spring+Struts+Hibernate实现的健康管理平台
2019-04-30
基于spring+struts2+hibernate实现的Java web论坛
2019-04-30
基于SSH保险业务管理系统的设计与实现
2019-04-30
基于SSH框架的电影订票系统网站的设计与实现
2019-04-30
基于SSM和MySQL实现的多业务农情信息云平台
2019-04-30
马原复习笔记(老师勾画的重点以及相应的习题练习)
2019-04-30
嵌入式系统开发(STM32)复习笔记
2019-04-30
数据挖掘概念与技术复习
2019-04-30
洋酒销售系统的设计与实现
2019-04-30
javaWeb校园二手平台项目
2019-04-30
java的陶瓷工厂进销存管理系统的设计与实现
2019-04-30
java物流网站的设计与实现
2019-04-30