1 package cz.cuni.amis.utils.astar;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Comparator;
6 import java.util.HashMap;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Set;
10
11
12
13
14
15
16
17 public class AStarHeap<NODE> implements Collection<NODE> {
18
19 private NODE[] nodes;
20 private int count;
21 private int items;
22 private HashMap<NODE, Integer> references;
23 private Comparator<NODE> cmp;
24
25 private void grow(){
26 NODE[] tempNodes = (NODE[]) new Object[count*2];
27 for (int i = 0; i <= items; ++i){
28 tempNodes[i] = nodes[i];
29 }
30 nodes = tempNodes;
31 count = count * 2;
32 }
33
34 private int left(int reference){
35 return 2*reference;
36 }
37
38 private int right(int reference){
39 return 2*reference+1;
40 }
41
42 private int upRef(int reference){
43 return reference / 2;
44 }
45
46 private NODE getNode(int reference){
47 while (reference >= count)
48 grow();
49 return nodes[reference];
50 }
51
52 private int downNode(int reference){
53 NODE currentNode = getNode(reference);
54 if (currentNode == null) {
55 return reference;
56 }
57 NODE leftNode = null;
58 NODE rightNode = null;
59 int way = 0;
60
61 while (true){
62 way = 0;
63 leftNode = getNode(left(reference));
64 rightNode = getNode(right(reference));
65
66 if ((leftNode == null) && (rightNode == null)){
67 references.put(currentNode, reference);
68 return reference;
69 }
70 if (rightNode == null) way = -1;
71 else
72 if (leftNode == null) way = 1;
73 if (way == 0) way = cmp.compare(leftNode, rightNode);
74
75 if (way < 0){
76
77 if (cmp.compare(currentNode, leftNode) > 0){
78 nodes[reference] = leftNode;
79 references.put(leftNode, new Integer(reference));
80 reference = left(reference);
81 nodes[reference] = currentNode;
82 } else {
83 references.put(currentNode, reference);
84 return reference;
85 }
86 } else {
87
88 if (cmp.compare(currentNode, rightNode) > 0){
89 nodes[reference] = rightNode;
90 references.put(rightNode, new Integer(reference));
91 reference = right(reference);
92 nodes[reference] = currentNode;
93
94 } else {
95 references.put(currentNode, reference);
96 return reference;
97 }
98 }
99 }
100 }
101
102 private int upNode(int reference){
103 if (reference == 1)
104 return reference;
105 NODE currentNode = getNode(reference);
106 if (currentNode == null)
107 return reference;
108 NODE upNode = null;
109 while (reference > 1){
110 upNode = getNode(upRef(reference));
111 if (cmp.compare(currentNode, upNode) < 0){
112 nodes[reference] = upNode;
113 references.put(upNode, reference);
114 reference = upRef(reference);
115 } else {
116 break;
117 }
118 }
119 nodes[reference] = currentNode;
120 references.put(currentNode, reference);
121 return reference;
122 }
123
124 private void initHeap(int capacity){
125 if (capacity < 2) capacity = 2;
126 nodes = (NODE[]) new Object[capacity];
127 count = capacity;
128 items = 0;
129 references = new HashMap(capacity);
130 }
131
132 public AStarHeap(Comparator<NODE> comp, int capacity){
133 initHeap(capacity);
134 cmp = comp;
135 }
136
137 public AStarHeap(Comparator<NODE> comp){
138 initHeap(20);
139 cmp = comp;
140 }
141
142 public NODE getMin(){
143 return nodes[1];
144 }
145
146 public boolean deleteMin(){
147 if (items == 0)
148 return false;
149 return remove(nodes[1], 1);
150 }
151
152 public boolean decreaseKey(NODE arg0){
153 Integer reference = (Integer)references.get(arg0);
154 if (reference == null){
155 return add(arg0);
156 }
157 upNode(reference.intValue());
158 return true;
159 }
160
161 public boolean add(NODE arg0) {
162 Integer reference = (Integer)references.get(arg0);
163 if (reference == null){
164 getNode(items+1);
165 nodes[items+1] = arg0;
166 upNode(items+1);
167 items = items + 1;
168 return true;
169 } else {
170 int tempRef = upNode(reference.intValue());
171 if (tempRef == reference.intValue())
172 downNode(reference.intValue());
173 return true;
174 }
175 }
176
177 @Override
178 public boolean addAll(Collection arg0) {
179 Iterator<NODE> iter = arg0.iterator();
180 while (iter.hasNext())
181 add(iter.next());
182 return true;
183 }
184
185 public boolean addAll(NODE[] arg0){
186 boolean ok = true;
187 for (int i = 0; i < arg0.length; ++i){
188 ok = this.add(arg0[i]) && ok;
189 }
190 return ok;
191 }
192
193 public void clear() {
194 for (int i = 0; i < count; ++i){
195 nodes[i] = null;
196 references.clear();
197 }
198 }
199
200 public boolean contains(Object arg0) {
201 return references.containsKey(arg0);
202 }
203
204 public boolean containsAll(Collection arg0) {
205 return references.containsKey(arg0);
206 }
207
208 public boolean containsAll(Object[] arg0) {
209 for (int i = 0; i < arg0.length; ++i){
210 if (!this.contains(arg0[i])) {
211 return false;
212 }
213 }
214 return true;
215 }
216
217 public boolean isEmpty() {
218 return references.isEmpty();
219 }
220
221 public Iterator<NODE> iterator() {
222 return new AStarHeapIterator<NODE>(nodes, items, this);
223 }
224
225 private boolean remove(NODE arg0, int reference){
226 references.remove(arg0);
227 if (items == 1){
228 nodes[1] = null;
229 items = 0;
230 return true;
231 }
232 nodes[reference] = nodes[items];
233 nodes[items] = null;
234 items = items - 1;
235 downNode(reference);
236 return true;
237 }
238
239 public boolean remove(Object arg0) {
240 Integer reference = (Integer)references.get(arg0);
241 if (reference == null)
242 return false;
243 return remove(reference.intValue());
244 }
245
246 public boolean removeAll(Collection arg0) {
247 Iterator iter = arg0.iterator();
248 while (iter.hasNext())
249 remove(iter.next());
250 return true;
251 }
252
253 public boolean retainAll(Collection arg0) {
254 Iterator iter = references.keySet().iterator();
255 Object item; Integer reference;
256 while (iter.hasNext()){
257 item = iter.next();
258 reference = (Integer)references.get(item);
259 if (!arg0.contains(item)) remove((NODE) item, reference.intValue());
260 }
261 return true;
262 }
263
264 public int size() {
265 return items;
266 }
267
268 public boolean empty() {
269 return items == 0;
270 }
271
272 public Object[] toArray() {
273 return references.keySet().toArray();
274 }
275
276 public Object[] toArray(Object[] arg0) {
277 return references.keySet().toArray(arg0);
278 }
279
280 public Set toSet(){
281 return references.keySet();
282 }
283
284
285
286
287
288
289 public static String mainToStr(Integer[] nums){
290 if (nums.length == 0) return "";
291 String str = nums[0].toString();
292 for (int i = 1; i < nums.length; ++i){
293 str += ", " + nums[i].toString();
294 }
295 return str;
296 }
297
298 public static boolean mainCheck(AStarHeap heap, Integer[] nums){
299 System.out.println("Removing and checking " + mainToStr(nums));
300 List heapInts = new ArrayList();
301 List desiredInts = new ArrayList();
302 for (int i = 0; i < nums.length; ++i){
303 desiredInts.add(nums[i]);
304 heapInts.add(heap.getMin());
305 heap.deleteMin();
306 }
307 if ( heapInts.containsAll(desiredInts) ){
308 System.out.println("OK");
309 return true;
310 } else {
311 System.out.println("KO!");
312 System.exit(1);
313 }
314 return false;
315 }
316
317 public static void mainAdd(AStarHeap heap, Integer[] nums){
318 System.out.println("Adding: " + mainToStr(nums));
319 for (int i = 0; i < nums.length; ++i){
320 heap.add(nums[i]);
321 }
322 }
323
324 public static void main(String[] args){
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 }
347
348 }