O(logn)的查找數組區間和以及修改數組中的值
涉及到的知識點
其中涉及到的操做
- build_tree()把一個數字構建成一個樹
- query_tree()返回L,R一個區間的和
- update_tree()更改數組中的下標爲idx值爲val
![SegmentTree](http://static.javashuo.com/static/loading.gif)
完整代碼
#include<stdio.h>
#define MAX_LEN 100000
void build_tree(int arr[], int tree[], int node, int start, int end) {
if (start == end) { //遞歸出口
tree[node] = arr[start];
return;
}
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); //[start, mid]的區間
build_tree(arr, tree, right_node, mid + 1, end);// [mid + 1, end]的區間
tree[node] = tree[left_node] + tree[right_node]; // 樹的結點爲左右子結點的和
}
void update_tree(int arr[], int tree[], int node, int start, int end, int idx, int val) {
if (start == end) { // 遞歸出口
arr[idx] = val; // 修改數組的值
tree[node] = val;// 更改樹的結點值
return;
}
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
if (start <= idx && idx <= mid) { //在左子區間
update_tree(arr, tree, left_node, start, mid, idx, val);
}
else { // 在右子區間
update_tree(arr, tree, right_node, mid + 1, end, idx, val);
}
tree[node] = tree[left_node] + tree[right_node];
}
int query_tree(int arr[], int tree[], int node, int start, int end,int L, int R) {
if (R < start || L > end) { //不知足區間要求 返回0
return 0;
}
else if (start == end) { //到了葉子結點返回
return tree[node];
}
else if (R >= end && L <= start) { //結點在LR範圍以內
return tree[node];
}
int mid = (start + end) / 2;
int left_node = node * 2 + 1;
int right_node = node * 2 + 2;
int sum_left = query_tree(arr, tree, left_node, start, mid, L, R);
int sum_right = query_tree(arr, tree, right_node, mid + 1, end, L, R);
return sum_left + sum_right;
}
int main() {
int arr[] { 1, 3, 5, 7, 9 ,11};
int size = 6;
int tree[MAX_LEN] = { 0 };
build_tree(arr, tree, 0, 0, size - 1);
update_tree(arr, tree, 0, 0, size - 1, 4, 6);
int s = query_tree(arr, tree, 0, 0, size - 1, 2, 5);
printf("%d\n", s);
return 0;
}