线段树(segment tree) code

来源:互联网 发布:济南java培训 编辑:程序博客网 时间:2024/05/22 07:01

线段树(segment tree)


线段树是一棵二叉树,记为T(a, b),参数a,b表示区间[a,b],其中b-a称为区间的长度,记为L。

线段树T(a,b)递归定义类似为:

若L>1 :  [a, (a+b) div 2]为 T的左儿子;             [(a+b) div 2,b]为T 的右儿子。 若L=1 : T为叶子节点。

上面的线段树只是一种可能的形式,具体按自己的需求定义,只要保证父节点“覆盖”所有的子节点


例:

桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如图所示。现在从桌子的前方射来一束平行光, 把盒子的影子投射到了墙上。问影子的总宽度是多少?

这道题目是一个经典的模型。在这里,我们略去某些处理的步骤,直接分析重点问题,可以把题目抽象地描述如下:x轴上有若干条线段,求线段覆盖的总长度,即S1+S2的长度。


code:

#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct Node{int lvalue, rvalue;int data;struct Node *lchild;struct Node *rchild;} Node;Node  *Build(int l, int r){Node *root;if (l >= r)return NULL;root = (Node *)calloc(1, sizeof(Node));root->lvalue = l;root->rvalue = r;root->data = 0;root->lchild = NULL;root->rchild = NULL;if (l + 1 < r) {int  mid = (l + r) >> 1;root->lchild = Build(l , mid) ;root->rchild = Build(mid , r) ; } return root; }void  Insert(Node *root, int c, int d){if (!root)return;if(c <= root->lvalue && d >= root->rvalue) root->data++;else {int mid = (root->lvalue + root->rvalue) >> 1;if (d <= mid) Insert(root->lchild, c, d);else if(c >= mid) Insert(root->rchild, c, d);else {Insert(root->lchild, c, mid);Insert(root->rchild, mid, d);}}} void  Delete(Node *root, int c, int d){if (!root)return;if (c <= root->lvalue && d >= root->rvalue) root->data--;else {int mid = (root->lvalue + root->rvalue) >> 1;if (d <= mid) Delete(root->lchild, c, d);else if(c >= mid) Delete(root->rchild, c, d);else {Delete(root->lchild, c, mid);Delete(root->rchild, mid, d);}}} void Find(Node *root,int a,int b, int *count)  {  int mid;if (!root)return;if(root->data > 0) {*count += (root->rvalue - root->lvalue);  return;  }mid = (root->lvalue + root->rvalue) >> 1;  if(b <= mid)   Find(root->lchild, a, b, count);  else if(a >= mid)   Find(root->rchild,a, b, count);else {  Find(root->lchild, a, mid, count);  Find(root->rchild, mid, b, count);  }  }int value[][2] = {{1, 7},{8, 17},{15, 23},{34, 40},{38, 42},{36, 41}};int main(){int count = 0;int i;Node *root = Build(9, 101);for (i = 0; i < sizeof(value) / sizeof(value[0]); i++)Insert(root, value[i][0], value[i][1]);Find(root, 4, 50, &count);printf("count: %d\n", count);Delete(root, 36, 41);count = 0;Find(root, 4, 50, &count);printf("count: %d\n", count);Delete(root, 38, 42);count = 0;Find(root, 4, 50, &count);printf("count: %d\n", count);return 0;}




0 0
原创粉丝点击