返回
从零开始,用Java轻松搞定线段树
后端
2024-02-06 09:38:32
线段树,作为一种树形数据结构,因其区间更新和查询的特性,常用于动态规划等算法中。线段树的节点对应一个区间,每个节点都包含了该区间的相关信息,如区间和、区间最大值、区间最小值等。
要实现线段树,我们首先需要了解线段树的基本结构。线段树由一个根节点和若干个子节点组成,每个子节点都对应一个区间。根节点的区间是整个待处理区间,而子节点的区间则是根节点区间的子区间。这种层级结构使得线段树可以高效地处理区间更新和查询。
其次,我们需要了解线段树的存储方式。线段树一般采用数组来存储,其中每个元素对应一个线段树节点。数组的索引与区间端点相关,这样就可以通过索引快速找到对应区间的节点。
线段树的构建过程如下:
- 将待处理区间划分为若干个子区间。
- 将根节点的区间设置为待处理区间。
- 将待处理区间划分为左右两个子区间。
- 创建两个子节点,分别对应左右子区间。
- 将根节点的左右子节点分别指向两个子节点。
- 递归地将左右子区间划分为更小的子区间,并创建相应的子节点。
- 直到所有子区间都包含一个元素或为空时停止划分。
线段树的更新操作如下:
- 找到待更新区间的节点。
- 更新该节点的信息。
- 如果该节点不是叶子节点,则递归地更新其子节点的信息。
线段树的查询操作如下:
- 找到待查询区间的节点。
- 返回该节点的信息。
- 如果该节点不是叶子节点,则递归地查询其子节点的信息。
为了加深理解,我们提供了一个用Java实现的线段树示例代码:
class SegmentTree {
private int[] tree;
private int[] arr;
private int n;
public SegmentTree(int[] arr) {
this.arr = arr;
n = arr.length;
tree = new int[4 * n];
build(1, 0, n - 1);
}
private void build(int node, int start, int end) {
if (start == end) {
tree[node] = arr[start];
return;
}
int mid = (start + end) / 2;
build(2 * node, start, mid);
build(2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] + tree[2 * node + 1];
}
public int query(int start, int end) {
return query(1, 0, n - 1, start, end);
}
private int query(int node, int start, int end, int l, int r) {
if (l > end || r < start) {
return 0;
}
if (l <= start && r >= end) {
return tree[node];
}
int mid = (start + end) / 2;
int leftSum = query(2 * node, start, mid, l, r);
int rightSum = query(2 * node + 1, mid + 1, end, l, r);
return leftSum + rightSum;
}
public void update(int index, int value) {
update(1, 0, n - 1, index, value);
}
private void update(int node, int start, int end, int index, int value) {
if (index < start || index > end) {
return;
}
if (start == end) {
tree[node] = value;
return;
}
int mid = (start + end) / 2;
update(2 * node, start, mid, index, value);
update(2 * node + 1, mid + 1, end, index, value);
tree[node] = tree[2 * node] + tree[2 * node + 1];
}
}
public class Main {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
SegmentTree segmentTree = new SegmentTree(arr);
System.out.println("查询区间[1, 3]的和:" + segmentTree.query(1, 3));
segmentTree.update(2, 10);
System.out.println("修改下标为2的元素为10后,查询区间[1, 3]的和:" + segmentTree.query(1, 3));
}
}
这个示例代码展示了如何用Java实现线段树,包括构建、查询和更新操作。在主函数中,我们创建了一个线段树对象,并对该对象进行了一系列操作,包括查询和更新。输出结果如下:
查询区间[1, 3]的和:10
修改下标为2的元素为10后,查询区间[1, 3]的和:19
通过这个示例代码,你应该对线段树有了更深入的理解。希望本文能帮助你掌握线段树的基本原理和实现方法,以便你能在你的项目中应用它。