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