一、线段树基本概念

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
    对于线段树中的每一个非叶子节点[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],线段树需要的空间为数组大小的四倍

二、线段树的存储数据结构

由上面的图可以看出,存储一颗线段树和二叉树有点类似,需要左孩子和右孩子节点,另外,为了存储每条线段出现的次数,所以一般会加上计数的元素,其具体如下:

  1. struct Node         // 线段树
  2. {
  3. int left;
  4. int right;
  5. int counter;
  6. }segTree[4*BORDER];
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、线段树的创建

  1. /* 构建线段树 根节点开始构建区间[lef,rig]的线段树*/
  2. void construct(int index, int lef, int rig)
  3. {
  4. segTree[index].left = lef;
  5. segTree[index].right = rig;
  6. if(lef == rig)   // 叶节点
  7. {
  8. segTree[index].counter = 0;
  9. return;
  10. }
  11. int mid = (lef+rig) >> 1;
  12. construct((index<<1)+1, lef, mid);
  13. construct((index<<1)+2, mid+1, rig);
  14. segTree[index].counter = 0;
  15. }
/* 构建线段树 根节点开始构建区间[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、线段树的元素插入

  1. /* 插入线段[start,end]到线段树, 同时计数区间次数 */
  2. void insert(int index, int start, int end)
  3. {
  4. if(segTree[index].left == start && segTree[index].right == end)
  5. {
  6. ++segTree[index].counter;
  7. return;
  8. }
  9. int mid = (segTree[index].left + segTree[index].right) >> 1;
  10. if(end <= mid)//左子树
  11. {
  12. insert((index<<1)+1, start, end);
  13. }else if(start > mid)//右子树
  14. {
  15. insert((index<<1)+2, start, end);
  16. }else//分开来了
  17. {
  18. insert((index<<1)+1, start, mid);
  19. insert((index<<1)+2, mid+1, end);
  20. }
  21. }
/* 插入线段[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、线段树的元素查找

  1. /* 查询点x的出现次数
  2. * 从根节点开始到[x,x]叶子的这条路径中所有点计数相加方为x出现次数
  3. */
  4. int query(int index, int x)
  5. {
  6. if(segTree[index].left == segTree[index].right) // 走到叶子,返回
  7. {
  8. return segTree[index].counter;
  9. }
  10. int mid = (segTree[index].left+segTree[index].right) >> 1;
  11. if(x <= mid)
  12. {
  13. return segTree[index].counter + query((index<<1)+1,x);
  14. }
  15. return segTree[index].counter + query((index<<1)+2,x);
  16. }
/* 查询点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、线段树的元素删除

  1. void  delete_ (int c , int  d, int index)
  2. {
  3. if(c <= segTree[index].left && d >= segTree[index].right)
  4. segTree[index].counter--;
  5. else
  6. {
  7. if(c < (segTree[index].left + segTree[index].right)/2 ) delete_( c,d, segTree[index].left);
  8. if(d > (segTree[index].left + segTree[index].right)/2 ) delete_( c,d, segTree[index].right);
  9. }
  10. }

文章转载自:http://www.iteblog.com/archives/144

线段树的创建插入查找删除相关推荐

  1. c语言 trie树,C语言实现Trie树(字典树)的插入查找删除与遍历操作

    Trie树,也称作是字典树,是一种哈希树的变种,查询效率较高.Trie树可以用于统计或者排序大量的字符串,比如对一系列字符串按照字典序排序. 字典树是一个多叉树,每一个节点上存储的不是一个字符串,而是 ...

  2. 线段树线段树的创建线段树的查询单节点更新区间更新

    目录 线段树 什么是线段树? 线段树的创建 线段树的查询 单节点更新 区间更新 未完待续 线段树 实现问题:常用于求数组区间最小值 时间复杂度:(1).建树复杂度:nlogn.(2).线段树算法复杂度 ...

  3. hdu4267线段树段更新,点查找,55棵线段树.

    题意:      给你N个数,q组操作,操作有两种,查询和改变,查询就是查询当前的这个数上有多少,更改是给你a b k c,每次从a到b,每隔k的数更改一次,之间的数不更改,就相当于跳着更新. 思路: ...

  4. 字典树简单实现 插入 查找 遍历

    字典树是一种存储字符串的高效的结构,它保存了不同字符的相同前缀,又因此叫做前缀树,使用前缀,大大避免相同字符的重复匹配,加快查找效率 字典树是一颗多叉树,比如存储26个字母的,那么就有26叉 字典树的 ...

  5. 洛谷 P3368 【模板】树状数组 2(线段树区间加单点查找)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入格式 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个 ...

  6. Codeforces Round #413 C. Fountains (线段树的创建、查询、更新)

     vj题目链接: https://vjudge.net/contest/235444#problem/F 题意: 有 n 个待建的喷泉,每个的建造代价为pi coins或者pi diamonds(co ...

  7. 线段树——操作格子(蓝桥杯试题集)

    题目链接: http://lx.lanqiao.cn/problem.page?gpid=T18 题目描述: 有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个 ...

  8. 【算法微解读】浅谈线段树

    浅谈线段树 (来自TRTTG大佬的供图) 线段树个人理解和运用时,认为这个是一个比较实用的优化算法. 这个东西和区间树有点相似,是一棵二叉搜索树,也就是查找节点和节点所带值的一种算法. 使用线段树可以 ...

  9. CodeForces - 1417F Graph and Queries(克鲁斯卡尔重构树的dfs序上建线段树)

    题目链接:点击查看 题目大意:给出一个 n 个点 m 条边组成的无向图,每个点初始时都有一个权值 val,满足: 每个点的 val[ i ] 各不相同 val[ i ] ∈ [ 1 , n ] 现在有 ...

最新文章

  1. 赫夫曼编码(基于赫夫曼树的实现)
  2. GraphNVP | 用于分子图生成的可逆流模型
  3. Android中的ImageView的getDrawableCache获取背景图片的时候注意的问题
  4. JavaScript(十三)面向对象
  5. Chrome Native Client 原理
  6. 使用PostgREST构建PostgreSQL数据库的REST风格API
  7. Android学习点点滴滴之获取正在运行的进程
  8. wxPython多个窗口的基本结构
  9. App Store审核宝典
  10. mysql主从配置查看_MySQL主从配置 - MySQL入门教程_数据库技术_Linux公社-Linux系统门户网站...
  11. matlab伏安特性曲线的图,电源伏安特性曲线的意义详细解析
  12. jitsi各工程编译笔记(一)各工程大概
  13. 服务器装win7没有硬盘分区,深度win7安装没有磁盘分区怎么办?
  14. Scratch中做一个简单迷宫小游戏,值得您收藏!
  15. C语言atoi、atol、atoll和atoq函数
  16. DEDECMS站点内容怎么自动更新到新浪微博
  17. CentOS7中文输入法,拼音输入法
  18. 恒压板框过滤实验数据处理_鞍山高温除尘袋公司,板框压滤机滤布,热门_泰翔工业滤料...
  19. No view found for id 0x7f05003c (*) for fragment PlaceholderFragment
  20. 装饰模式实例与解析 实例一:变形金刚

热门文章

  1. vue 数组删除(对象)单条删除,多条删除
  2. 视频直播取代微博不是天方夜谭
  3. python中显示图片和文字
  4. TInkPadT490s+单硬盘 Ubutun+Win10双系统安装问题总结
  5. Unity——在运行时修改Animator Controller状态机中的动画片段
  6. vmware下Ubuntu挂载U盘
  7. openGauss单机版升级示例(2.0.1—>3.1.1)
  8. 秀米编辑器(xiumi)+百度编辑器(Ueditor) 集成 :解决集成问题,秀米编辑器导出到百度编辑器格式问题,图片保存到自己的服务器(阿里云OSS)
  9. 高考400分计算机专业,高考400分 计算机专业
  10. python 将图片转换成像素画_Python用61行代码实现图片像素化