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 package org.utgenome.gwt.utgb.client.canvas;
26
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Stack;
31
32
33
34
35
36
37
38 public class PrioritySearchTree<E> implements Iterable<E> {
39
40 public class Node {
41 public E elem;
42 public int x;
43 public int y;
44 public int splitX;
45 public Node left;
46 public Node right;
47
48 public Node(E node, int x, int y) {
49 if (node == null)
50 throw new NullPointerException("node cannot be null");
51 this.elem = node;
52 this.x = x;
53 this.y = y;
54 }
55
56 public void swap(Node n) {
57
58 int tmpX = this.x;
59 this.x = n.x;
60 n.x = tmpX;
61
62
63 int tmpY = this.y;
64 this.y = n.y;
65 n.y = tmpY;
66
67
68 E tmpNode = this.elem;
69 this.elem = n.elem;
70 n.elem = tmpNode;
71 }
72
73 public void replaceWith(Node n) {
74 this.x = n.x;
75 this.y = n.y;
76 this.elem = n.elem;
77 }
78 }
79
80 private Node root = null;
81 private int lowerBoundOfX = 0;
82 private int upperBoundOfX = Integer.MAX_VALUE;
83 private int lowerBoundOfY = 0;
84 private int uppperBoundOfY = Integer.MAX_VALUE;
85 private int nodeCount = 0;
86
87 public PrioritySearchTree() {
88
89 }
90
91 public PrioritySearchTree(int lowerBoundOfX, int upperBoundOfX, int lowerBoundOfY, int upperBoundOfY) {
92 this.lowerBoundOfX = lowerBoundOfX;
93 this.upperBoundOfX = upperBoundOfX;
94 this.lowerBoundOfY = lowerBoundOfY;
95 this.uppperBoundOfY = upperBoundOfY;
96 }
97
98 public static interface Visitor<E> {
99 public void visit(E visit);
100 }
101
102 private class DFSIterator implements Iterator<E> {
103
104 private Stack<Node> nodeStack = new Stack<Node>();
105
106 public DFSIterator(Node root) {
107 if (root != null)
108 nodeStack.push(root);
109 }
110
111 public boolean hasNext() {
112 return !nodeStack.isEmpty();
113 }
114
115 public E next() {
116 if (nodeStack.isEmpty())
117 return null;
118
119 Node nextNode = nodeStack.pop();
120 if (nextNode.right != null)
121 nodeStack.push(nextNode.right);
122 if (nextNode.left != null)
123 nodeStack.push(nextNode.left);
124
125 return nextNode.elem;
126 }
127
128 public void remove() {
129 throw new UnsupportedOperationException("remove");
130 }
131
132 }
133
134 public Iterator<E> iterator() {
135 return new DFSIterator(root);
136 }
137
138 public void depthFirstSearch(Visitor<E> visitor) {
139 dfs(root, visitor);
140 }
141
142 private void dfs(Node current, Visitor<E> visitor) {
143 if (current == null)
144 return;
145 visitor.visit(current.elem);
146 dfs(current.left, visitor);
147 dfs(current.right, visitor);
148 }
149
150 private static class QueryBox {
151 public final int x1;
152 public final int x2;
153 public final int upperY;
154
155 public QueryBox(int x1, int x2, int upperY) {
156 this.x1 = x1;
157 this.x2 = x2;
158 this.upperY = upperY;
159 }
160
161 }
162
163 public void clear() {
164 root = null;
165 nodeCount = 0;
166 }
167
168 public int size() {
169 return nodeCount;
170 }
171
172
173
174
175
176
177
178
179
180
181 public List<E> rangeQuery(int x1, int x2, int upperY) {
182 ArrayList<E> result = new ArrayList<E>();
183 ResultCollector<E> resultCollector = new ResultCollector<E>();
184 rangeQuery_internal(root, new QueryBox(x1, x2, upperY), x1, x2, resultCollector);
185 return resultCollector.result;
186 }
187
188 public void rangeQuery(int x1, int x2, int upperY, ResultHandler<E> handler) {
189 rangeQuery_internal(root, new QueryBox(x1, x2, upperY), x1, x2, handler);
190 }
191
192 public static interface ResultHandler<E> {
193 public void handle(E elem);
194
195 public boolean toContinue();
196 }
197
198 private static class ResultCollector<E> implements ResultHandler<E> {
199
200 public List<E> result = new ArrayList<E>();
201
202 public void handle(E elem) {
203 result.add(elem);
204 }
205
206 public boolean toContinue() {
207 return true;
208 }
209
210 }
211
212 boolean rangeQuery_internal(Node currentNode, QueryBox queryBox, int rangeX1, int rangeX2, ResultHandler<E> resultHandler) {
213 boolean toContinue = resultHandler.toContinue();
214 if (!toContinue)
215 return false;
216
217 if (currentNode != null) {
218 if (currentNode.y <= queryBox.upperY) {
219
220 if (queryBox.x1 <= currentNode.x && currentNode.x <= queryBox.x2) {
221
222 resultHandler.handle(currentNode.elem);
223 toContinue = resultHandler.toContinue();
224 }
225
226
227 int middleX = currentNode.splitX;
228
229
230 if (toContinue && queryBox.x1 < middleX) {
231 toContinue = rangeQuery_internal(currentNode.left, queryBox, rangeX1, middleX, resultHandler);
232 }
233
234
235 if (toContinue && middleX <= queryBox.x2) {
236 toContinue = rangeQuery_internal(currentNode.right, queryBox, middleX, rangeX2, resultHandler);
237 }
238 }
239 }
240
241 return toContinue;
242
243 }
244
245
246
247
248
249
250 public void insert(E elem, int x, int y) {
251 root = insert_internal(root, new Node(elem, x, y), lowerBoundOfX, upperBoundOfX);
252 }
253
254
255
256
257
258
259
260 public boolean remove(E elem, int x, int y) {
261 int prevNumNodes = size();
262 root = remove_internal(root, new Node(elem, x, y), lowerBoundOfX, upperBoundOfX);
263 return prevNumNodes != size();
264 }
265
266 Node insert_internal(Node currentNode, Node insertNode, int lowerRangeOfX, int upperRangeOfX) {
267 if (currentNode == null) {
268
269 currentNode = insertNode;
270 currentNode.splitX = (lowerRangeOfX + upperRangeOfX) / 2;
271 nodeCount++;
272 }
273 else {
274 if (insertNode.y < currentNode.y) {
275 currentNode.swap(insertNode);
276 }
277
278 if (insertNode.x < currentNode.splitX)
279 currentNode.left = insert_internal(currentNode.left, insertNode, lowerRangeOfX, currentNode.splitX);
280 else
281 currentNode.right = insert_internal(currentNode.right, insertNode, currentNode.splitX, upperRangeOfX);
282 }
283
284 return currentNode;
285 }
286
287 Node remove_internal(Node currentNode, Node removeTarget, int x_lower, int x_upper) {
288 if (currentNode == null) {
289
290 return currentNode;
291 }
292
293 if (currentNode.elem.equals(removeTarget.elem)) {
294
295 if (currentNode.left != null) {
296 if (currentNode.right != null) {
297 if (currentNode.left.y < currentNode.right.y) {
298
299 currentNode.replaceWith(currentNode.left);
300 currentNode.left = remove_internal(currentNode.left, currentNode.left, x_lower, x_upper);
301 }
302 else {
303
304 currentNode.replaceWith(currentNode.right);
305 currentNode.right = remove_internal(currentNode.right, currentNode.right, x_lower, x_upper);
306 }
307 }
308 else {
309
310 currentNode.replaceWith(currentNode.left);
311 currentNode.left = remove_internal(currentNode.left, currentNode.left, x_lower, x_upper);
312 }
313
314 }
315 else {
316 if (currentNode.right != null) {
317
318 currentNode.replaceWith(currentNode.right);
319 currentNode.right = remove_internal(currentNode.right, currentNode.right, x_lower, x_upper);
320 }
321 else {
322
323 nodeCount--;
324 return null;
325 }
326 }
327 }
328 else {
329
330 if (removeTarget.x < currentNode.splitX)
331 currentNode.left = remove_internal(currentNode.left, removeTarget, x_lower, currentNode.splitX);
332 else
333 currentNode.right = remove_internal(currentNode.right, removeTarget, currentNode.splitX, x_upper);
334 }
335
336 return currentNode;
337 }
338
339 }