数据结构---线段树

 

一、目标:1.如何快速的查询出下列数组arr[2,5]的和  2。以及更新arr[4]为6。

                 用普通的方法查询的复杂度为O(n),更新的复杂度为O(1)。

                这时候我们可以用线段树来快速完成这些操作,复杂度为logn。

  

 

 

 

二、内容:如何创建,查询,更新线段树

public class QurQpd {
public static void main(String[] args) {
	int [] arr= {1,3,5,7,9,11};
	int [] tree=new int[10000];
	build_tree(arr,tree,0,0,5);
	System.out.println(qury_tree(arr, tree, 0, 0, 5, 4, 4));
	update_tree(arr, tree, 0, 0, 5, 4, 6);
	System.out.println(qury_tree(arr, tree, 0, 0, 5, 4, 4));
	
}
/*
 * 创建线段树
 */
static void  build_tree(int arr[],int tree[],int node,int start,int end) {
	if(start==end) {
		tree[node]=arr[start];
	}
	else {
	int mid=(start+end)/2;
	int left_node=2*node+1;
	int right_node=2*node+2;	
	build_tree(arr,tree,left_node,start,mid);
	build_tree(arr,tree,right_node,mid+1,end);
	tree[node]=tree[left_node]+tree[right_node];
}
}
/*
 * 查询数组下标[L,R]数组的和。
 */
static int qury_tree(int arr[],int tree[],int node,int start,int end,int L,int R) {
//第一个if要放在前边,不然会出错。原因:加入1,2if调换顺序,不符合条件的节点也会被算进去了。
if(end<L||start>R) {
		return 0;
	}
else if(start==end) {
	return tree[node];
}
else if(start>=L&&end<=R) {
		return tree[node];
	}
	else {
		int mid=(start+end)/2;
		int left_node=2*node+1;
		int right_node=2*node+2;	
		int a=qury_tree(arr,tree,left_node,start,mid,L,R);
		int b=qury_tree(arr,tree,right_node,mid+1,end,L,R);
		return a+b;
	}
}
/*
 * 更新下标为num的值为Val
 */
static void update_tree(int arr[],int tree[],int node,int start,int end,int num,int val) {
	if(end==start) {
		arr[num]=val;
		tree[node]=val;
	}
	else {
	int mid=(start+end)/2;
	int left_node=2*node+1;
	int right_node=2*node+2;	
	if(num<=mid)
		update_tree(arr, tree, left_node, start, mid, num, val);
	if(num>mid)
		update_tree(arr, tree, right_node, mid+1, end, num, val);
	tree[node]=tree[left_node]+tree[right_node];
}
}
}
  • 画出来的线段树:
  • 三、总结:
  • 写递归函数时,一定要用到if-else或者if-else if-else分支语句,否者函数没有出口。
  • 写更新方法的时候一直不明白为什么要用线段树来更新,这样复杂度不久为logn了,不是更复杂吗,为什么不直接修改(复杂度为O(1)。现在想通了,原因是:已经构造了线段树,假如直接修改arr[]的会导致线段树没有同时更新,线段树就是错的。
  •  
  •  
  •  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值