树的结构 数据结构_段树| 数据结构

树的结构 数据结构

What is a segment tree?

什么是段树?

A segment tree is a full binary tree where each node represents an interval. A node may store one or more data members of an interval which can be queried later.

段树是完整的二叉树,其中每个节点代表一个间隔。 节点可以存储一个或多个间隔的数据成员,以后可以查询该成员。

Why do we need Segment tree?

为什么我们需要细分树?

Many problems require that we give results based on query over a range or segment of available data. This can be the tedious and slow process, especially if the number of queries is large.

许多问题要求我们根据对可用数据范围或数据段的查询得出结果。 这可能是一个繁琐而缓慢的过程,尤其是在查询数量很大的情况下。

A segment tree lets us process such queries efficiently in logarithmic order of time.

段树使我们能够以对数时间顺序有效地处理此类查询。

How do we make a Segment tree?

我们如何制作细分树?

Let the data be in array arr[]

让数据位于数组arr []中

  1. The root of our tree will represent the entire interval of data we are interested in, i.e, arr[0...n-1].

    树的根将代表我们感兴趣的整个数据间隔,即arr [0 ... n-1] 。

  2. Each leaf of the tree will represent a range consisting of just a single element. Thus the leaves represent arr[0], arr[1], arr[2] ... arr[n-1].

    树的每片叶子将代表一个仅包含一个元素的范围。 因此,叶子代表arr [0] , arr [1] , arr [2] ... arr [n-1] 。

  3. The internal nodes will represent the merged result of their child nodes.

    内部节点将代表其子节点的合并结果。

  4. Each of the children nodes could represent approximately half of the range represented by their parent.

    每个子节点可代表其父节点所代表范围的大约一半。

Segment Tree generally contains three types of method: Build, Query, and Update.

细分树通常包含三种类型的方法:生成,查询和更新。

Let’s take an example:

让我们举个例子:

Problem: Range minimum query

问题:范围最小查询

You are given N numbers and Q queries. There are two types of queries.

系统会为您提供N个数字和Q个查询。 有两种类型的查询。

  1. Find the minimum number in range [l,r].

    在[l,r]范围内找到最小值。

  2. Update the element at ith position of array to val.

    将数组 i 位置的元素更新为val 。

Basic Approach:

基本方法:

We can find minimum element in O(N) and update the element in O(1). But if N or Q (query) is a very large number, it will be very slow.

我们可以在O(N)中找到最小元素,并在O(1)中更新元素。 但是,如果N或Q(查询)是一个非常大的数字,它将非常慢。

But it can be solved in logarithmic time with segment trees.

但这可以用段树在对数时间内解决。

  • The root of the tree is at index 1

    树的根在索引1处

  • The children then will be at 2*i and 2*i+1 index.

    然后,子级将位于2 * i和2 * i + 1索引处。

#include<iostream>

using namespace std;

int tree[400005]; // segment tree structure
int arr[100005];  // input tree

//Build

void build_tree(int node, int a, int b){
	//node represent the current node number
	// a,b represent the current node range
	//for leaf a == b
	if(a==b){
		//for single element minimum will be the element itself
		tree[node] = arr[a];
		return;
	}

	int mid = (a + b) >> 1; // middle element
	tree[node] =
	build_tree(node*2,a,mid)+    // call for left half
	build_tree(node*2+1,mid+1,b);//call for right half
}

//Query
int query_tree(int node, int a, int b, int i, int j){
	//i, j represents the range to be queried
	if(a > b || a > j || b < i){ return INT_MAX;} // out of range

	if(a>= i && b<=j){
		return tree[node];  //segment within range
	}

	int mid = a+ b >> 1;
	int q1 = query_tree(node*2,a,mid,i,j);    //left child query
	int q2 = query_tree(node*2+1,mid+1,b,i,j); // right child query

	return q1>q2?q2:q1;
}

void update_tree(int node, int a,int b, int i, int val){
	if(a>b||a>i||b<i){
		return;//Out of range
	}

	if(a==b){
		tree[node] = val;
		return;
	}

	int mid = (a+b) >> 1;

	tree[node] = update_tree(node*2,a,mid,i,val) +  // updating left child
	update_tree(node*2+1,mid+1,b,val); //updating right child
}


翻译自: https://www.includehelp.com/data-structure-tutorial/segment-trees.aspx

树的结构 数据结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值