-
Notifications
You must be signed in to change notification settings - Fork 85
/
Copy pathSegmentTree.java
199 lines (182 loc) · 4.38 KB
/
SegmentTree.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/**
* 线段树
*
* @author ronglexie
* @version 2018/8/25
*/
public class SegmentTree<E> {
/**普通数据*/
private E[] data;
/**树结构数据*/
private E[] tree;
/**融合器*/
private Merger<E> merger;
public SegmentTree(E[] arr,Merger<E> merger){
this.merger = merger;
data = (E[]) new Object[arr.length];
for (int i = 0; i < arr.length; i++) {
data[i] = arr[i];
}
tree = (E[]) new Object[4*arr.length];
buildSegmentTree(0, 0, data.length - 1);
}
/**
* 在treeIndex的位置创建表示区间[l...r]的线段树
*
* @param treeIndex
* @param l
* @param r
* @return void
* @author ronglexie
* @version 2018/8/25
*/
private void buildSegmentTree(int treeIndex, int l, int r) {
if(l == r){
tree[treeIndex] = data[l];
return;
}
int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex);
int middle = l + (r - l) / 2;
buildSegmentTree(leftTreeIndex,l,middle);
buildSegmentTree(rightTreeIndex,middle + 1,r);
//融合两个元素
tree[treeIndex] = merger.merge(tree[leftTreeIndex],tree[rightTreeIndex]);
}
public int getSize(){
return data.length;
}
public E get(int index){
if(index < 0 || index >= data.length){
throw new IllegalArgumentException("Index is illegal.");
}
return data[index];
}
/**
* 查找用数组实现的完全二叉树中该索引下节点的左孩子节点的索引
*
* @param index
* @return int
* @author ronglexie
* @version 2018/8/19
*/
public int leftChild(int index){
return (index * 2) + 1;
}
/**
* 查找用数组实现的完全二叉树中该索引下节点的右孩子节点的索引
*
* @param index
* @return int
* @author ronglexie
* @version 2018/8/19
*/
public int rightChild(int index){
return (index * 2) + 2;
}
/**
* 查询区间[start...end]的值
*
* @param start
* @param end
* @return E
* @author ronglexie
* @version 2018/8/25
*/
public E query(int start, int end){
if(start < 0 || start > data.length ||
end < 0 || end > data.length ||
start > end){
throw new IllegalArgumentException("Index is illegal.");
}
return query(0, 0, data.length-1, start, end);
}
/**
* 查询在以treeIndex为根的线段树区间为[l...r]的范围中,区间[start...end]的值
*
* @param treeIndex
* @param l
* @param r
* @param start
* @param end
* @return E
* @author ronglexie
* @version 2018/8/25
*/
private E query(int treeIndex, int l, int r, int start, int end){
if(l == start && r == end){
return tree[treeIndex];
}
int middle = l + (r - l) / 2;
int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex);
if(start >= middle + 1){
return query(rightTreeIndex,middle+1,r,start,end);
}else if(end <= middle){
return query(leftTreeIndex,l,middle,start,end);
}
E leftResult = query(leftTreeIndex, l, middle, start, middle);
E rightResult = query(rightTreeIndex, middle + 1, r, middle + 1, end);
return merger.merge(leftResult,rightResult);
}
/**
* 更新index位置的元素为e
*
* @param index
* @param e
* @return void
* @author ronglexie
* @version 2018/8/26
*/
public void set(int index, E e){
if(index < 0 || index >= data.length){
throw new IllegalArgumentException("Index is illegal.");
}
set(0,0,data.length - 1,index,e);
}
/**
* 更新在以treeIndex为根的线段树区间为[l...r]的范围中位置为index的值
*
* @param treeIndex
* @param l
* @param r
* @param index
* @param e
* @return void
* @author ronglexie
* @version 2018/8/26
*/
private void set(int treeIndex, int l, int r, int index, E e){
if(l == r){
tree[treeIndex] = e;
return;
}
int middle = l + (r - l) / 2;
int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex);
if(index >= middle + 1){
set(rightTreeIndex,middle+1,r,index,e);
}else if(index <= middle){
set(leftTreeIndex,l,middle,index,e);
}
tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("SegmentTree: [");
for (int i = 0; i < tree.length; i++) {
if (tree[i] != null){
result.append(tree[i]);
}else {
result.append("null");
}
if (i != tree.length - 1) {
result.append(",");
}else {
result.append("]");
}
}
return result.toString();
}
}