-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFibonacciHeap.java
340 lines (302 loc) · 12.5 KB
/
FibonacciHeap.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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
import java.util.*;
public class FibonacciHeap {
// ppinter to max value of the heap
Node root;
public FibonacciHeap() {
root = null;
}
// insert into the top level circular list
public void insert(Node node) {
//node needs to be inserted into the heap
//childCut value being set to false as it is being inserted into top level of the fibonacci heap
node.childCut = false;
if (root != null) {
Node firstnode = root;
// if heap contains a single element, i.e then it's right pointer is to itself
if (firstnode.right == firstnode) {
firstnode.left = node;
node.right = firstnode;
} else {
//contains more than 1 element
node.right = firstnode.right;
firstnode.right.left = node;
}
// Pointer to link the new node to the right of the current max element of the heap
firstnode.right = node;
node.left = firstnode;
node.childCut = false;
// Check whether the inserted node value is greater than the max node value
if (root.count < node.count)
root = node;
} else {
root = node;
node.right = node;
node.left = node;
}
}
// cascading cut is called on the parent of the removed node
// it is called till a childCut value of "false" is not encountered (or root node)
public void cascadingCut(Node node) {
Node par = node.parent;
// if there's a parent
if (par != null) {
// remove child from parent
Node newNode = remove(node);
// add to top level linked list
insert(newNode);
// Check whether the parent has childcut is TRUE
if (par.childCut) {
cascadingCut(par);
} else {
// if y is unmarked, set it marked
par.childCut = true;
node.childCut = false;
}
}
}
// add y as a child of x
public void addChild(Node x, Node y) {
// remove y from top list of heap
y.left.right = y.right;
y.right.left = y.left;
// make y a child of x
if (x.degree >= 1) {
//when x has one or more children already
// Insert the node as into the circular list of the parent
Node firstChild = x.child;
Node lastChild = firstChild.left;
firstChild.left = y;
lastChild.right = y;
y.left = lastChild;
y.right = firstChild;
} else {
//case for when x has no children
// Insert the child as the first child of the parent
x.child = y;
y.right = y;
y.left = y;
}
y.parent = x;
x.degree += 1;
}
// melding the heaps according to the degree
// public void meld(Node temp, HashMap<Integer, Node> map) {
// // System.out.println(temp.keyword);
// // check the degree of the entire top level list
// if (!map.containsKey(temp.degree))
// map.put(temp.degree, temp);
// Node currRight = root.right;
// //populate the hashmap
// //traverse for everynode
// while (currRight.right != root) {
// // Checking whether the given element exists in the hashtable and whether the degree of the current element is present in the hashtable
// // If there is an another element with same degree then combine the elements
// if (map.containsKey(currRight.degree) && !map.containsValue(currRight)) {
// // Extract the element from the hashtable/map that has the same degree as the current element of the circular list
// Node tempNode = map.remove(currRight.degree);
//
// // Check which element is bigger
// if (tempNode.count < currRight.count) {
// addChild(currRight, tempNode);
// meld(currRight, map);
// } else {
// addChild(tempNode, currRight);
// meld(tempNode, map);
// }
// // Invoke pairwise combine with the new combined element
// // meld(tempNode, map);
// break;
// } else {
// // Check whether the element is present in the hashtable
// if (!map.containsValue(currRight))
// map.put(currRight.degree, currRight);
// currRight = currRight.right;
// }
// }
// }
public void meld(Node temp, Map<Integer, Node> map) {
Node currRight = root.right;
while (currRight != root) {
// Checking whether the given element exists in the hashtable and whether the degree of the current
// element is present in the hashtable
// If there is an another element with same degree then combine the elements
if (map.containsKey(currRight.degree) && !map.containsValue(currRight)) {
// Extract the element from the hashtable/map that has the same degree
// as the current element of the circular list
// System.out.println("Map has " + map.size() + " elements");
Node tempNode = map.remove(currRight.degree);
// Check which element is bigger
if (tempNode.count < currRight.count) {
addChild(currRight, tempNode);
currRight = root.right; // restart process
} else {
addChild(tempNode, currRight);
currRight = root.right; // restart process
}
} else {
// Check whether the element is present in the hashtable
if (!map.containsValue(currRight))
map.put(currRight.degree, currRight);
currRight = currRight.right;
}
}
}
// function to reset the root pointer - to ensure it points to the max value
public void resetRootPointer() {
Node firstnode = root;
Node pointer = root;
Node tempmax = root;
boolean flag = true;
if (root == null) {
return;
}
while (pointer.right != firstnode) {
if (pointer.count > tempmax.count)
tempmax = pointer;
pointer = pointer.right;
flag = false;
}
if (!flag) {
if (pointer.count > tempmax.count)
tempmax = pointer;
}
root = tempmax;
}
// function removes the root node(maximum) and raises all it's children to the root-level circular linked list
public Node removeMax() {
Node removedNode = root;
root = removedNode.right;
// ensuring that the maximum node is not the only one in the list
if (removedNode != null) {
int numChild = removedNode.degree;
// case when the root node has no children
if (numChild == 0) {
// points to itself
if (removedNode.right == removedNode)
root = null;
else {
// Remove the root from top level circular linked list by resetting the Nodes on it's left and right
Node rightNode = removedNode.right;
Node leftNode = removedNode.left;
rightNode.left = leftNode;
leftNode.right = rightNode;
root = removedNode.right;
}
} else {
// when the root node has children, i.e, when numChild != 0
//remove every child of root node from it's sibling circular linked list and add it to the root or the top level list
if (removedNode.right == removedNode)
root = removedNode.child;
else {
// Pointer to the max and its adjacent element
Node leftNode = removedNode.left;
Node rightNode = removedNode.right;
// Pointer to the child element and its adjacent element
Node firstChild = removedNode.child;
Node lastChild = firstChild.left;
// children elements put into top level circular linkedList
leftNode.right = firstChild;
firstChild.left = leftNode;
rightNode.left = lastChild;
lastChild.right = rightNode;
}
}
// reset the pointers of the root node
removedNode.degree = 0;
removedNode.child = removedNode;
removedNode.right = removedNode;
removedNode.left = removedNode;
removedNode.parent = null;
// set the root node to point to the maximum
resetRootPointer();
root.parent = null;
Node maxSoFar = root;
// resetting parent values of the root level circular linked list (as new nodes have been added to it)
// also making sure all their childCut values are set to false
while (maxSoFar.right != root) {
maxSoFar.parent = null;
maxSoFar.childCut = false;
maxSoFar = maxSoFar.right;
}
maxSoFar.parent = null;
HashMap<Integer, Node> map = new HashMap<>();
meld(root, map);
}
return removedNode;
}
// detech an element node from it's parent node
Node remove(Node node) {
Node parent = node.parent;
// checking whether the node is at the root
if (node.parent == null)
return node;
// if parent has more than one child
if (parent.degree > 1) {
// remove the child from sibling circular linked list
Node nodeLeft = node.left;
Node nodeRight = node.right;
nodeLeft.right = nodeRight;
nodeRight.left = nodeLeft;
parent.child = nodeLeft;
} else
//remove the only child
parent.child = parent;
// decrease the degree of the parent and set the childcut of the parent to TRUE
parent.degree--;
parent.childCut = true;
// resetting the child node
node.left = node;
node.right = node;
node.parent = null;
// reset root pointer
resetRootPointer();
return node;
}
// increase the value of the count by some value
public void increaseKey(Node node, int incr) {
// calculating what the new count for the node should be
int new_value = node.count + incr;
node.count = new_value;
Node par = node.parent;
//checking if node belongs to the root level circular linked list
if (par == null) {
// if the updated value is greater than the root node
if (root.count < new_value) {
root = node;
}
} else {
// if the parent value is lesser than the count value - have to remove the child
if (par.count < node.count) {
//condition where the parent has not lost a child before
if (!par.childCut) {
//checking if the parent has more than one child
if (par.degree > 1) {
// removing the child, decreasing parent's degree
Node nodeLeft = node.left;
Node nodeRight = node.right;
nodeLeft.right = nodeRight;
nodeRight.left = nodeLeft;
par.child = nodeLeft;
par.degree -= 1;
} else {
// has only one child
// remove the link to the child from its parent
par.child = par;
par.degree = 0;
}
// updating the values of the node
node.parent = null;
node.count = new_value;
node.right = node;
node.left = node;
insert(node);
par.childCut = true;
} else {
node = remove(node);
insert(node);
cascadingCut(par);
}
}
}
}
}