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