-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFibHeap.java
426 lines (319 loc) · 15.2 KB
/
FibHeap.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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
import java.util.ArrayList;
import java.util.List;
public class FibHeap
{
private static final double matvariable=
1.0 / Math.log((1.0 + Math.sqrt(5.0)) / 2.0);
//Node class to create FibNode object
static class FibNode
{
FibNode parent, child, left, right;// parent , child and left+right siblings of type FibNode
int degree=0;//number of children to node
boolean childcut_value=false;//initial childcut value for all nodes is set to false
private String keyword;//the input keyword
Long hashvalue;//frequency of input keyword
FibNode(String keyword,Long hashvalue)//Constructor which initializes the keyword and its hashvalue
{
this.parent=null;//set parent of node (i.e. input keyword) to null
this.child=null; //set child of node to null
this.left=this;//set its left sibling
this.right=this;//set its right sibling
this.degree=0;//set number of children as 0
this.keyword=keyword;//assign the keyword
this.hashvalue=hashvalue;//assign the hashvalue
}
public String getKeyword()//Returns the keyword of the node
{
return this.keyword;
}
public long gethashvalue()//Returns the hashvalue associated with the keyword
{
return this.hashvalue;
}
public FibNode getParent() //Returns the parent of the node or keyword
{
return parent;
}
public void setParent(FibNode parent) //Assign the parent to the keyword
{
this.parent = parent;
}
public FibNode getLeft()//Returns the left sibling of the node
{
return left;
}
public void setLeft(FibNode left) //Assign the left sibling to the node
{
this.left = left;
}
public FibNode getRight() //Returns the right sibling of the node
{
return right;
}
public void setRight(FibNode right) //Assign the right sibling to the node
{
this.right = right;
}
public FibNode getChild()//Returns the child of the node
{
return child;
}
public void setChild(FibNode child) //Assign the child to the node
{
this.child = child;
}
public boolean isChildCut() //Returns the child cut value of the node
{
return childcut_value;
}
public void setChildCut(boolean childCut) //Returns the child cut value of the node
{
this.childcut_value = childCut;
}
}
private FibNode maxFibnode;//indicate the maximum hashvalue node
private int total_nodes;//total number of nodes
public int isEmpty(FibNode node) //This function checks whether a Node of type FibNode exists or not.
{
int flag=0;
if(node != null)//if node is not null
{
flag++;//increment the flag
return flag;//flag = 1 is node is not null
}
else
return flag;
}
private void sibling_link(FibNode m, FibNode n)//Insert node n between node m and node m.right
{
n.left = m;// left sibling of n is m
n.right = m.right;// assign m's right sibling to n's right
m.right = n;//n becomes m's right sibling
if (isEmpty(n.right)==0)//check if n's right is null or not
{
//if null
n.right = m;//assign n's right sibling as m
m.left = n;//assign n as m's left
// to maintain properties of circular doubly linked list
}
else
{
//if n's right sibling exist
n.right.left = n;// assign n as left sibling of n's right
}
}
private void left_right_merge(FibNode node) //This function is used to remove the input node by connecting its siblings together
{
node.left.right = node.right;//assign node's right to right of its left sibling
node.right.left = node.left;// assign node's left to left of its right sibling
}
private FibNode compare_hash(FibNode node,FibNode maxnode)
//This function is used to compare the hashvalue (frequencies) of two nodes: node and maxnode
{
if (node.hashvalue > maxnode.hashvalue) //if hashvalue of node is greater than the current
{
maxnode = node;//make node as max
}
return maxnode;//node with highest frequency
}
public void increasevalue(FibNode node, long value)//This function is used to increase the hashvalue ) of keyword (FibNode node)
{
node.hashvalue = value;// assign the value to node.hashvalue
FibNode node_parent = node.parent;//check with the parent's hashvalue
if((isEmpty(node_parent)!=0) && (node.hashvalue > node_parent.hashvalue)) //if parent exists and child has higher hashvalue perform cascading cut upto root based on childcut value
{
Nodecut(node, node_parent);//This function cuts the node from node_parent, and decreases the degree of node node_parent
Node_CascadingCut(node_parent);//This function is used to perform cascading cut based on the childcut _value
}
maxFibnode=compare_hash(node,maxFibnode);//This function is used to compare the hashvalue (frequencies) of two nodes: node and maxnode
}
public void insertnode(FibNode newnode)//This function is used to insert a new node of type FibNode into Fibonacci heap.
{
//First check if the maxFibnode is null(Empty heap).If the maxFibnode is null make this new node to be inserted as max .
if(isEmpty(maxFibnode)==0)
{
maxFibnode=newnode;
}
else
{
//If the max exists then link this new node as right sibling to maxFibnode using sibling_link function
sibling_link(maxFibnode,newnode);
//System.out.println("before "+maxFibnode.keyword);
maxFibnode=compare_hash(newnode,maxFibnode);//After insertion check the hashvalue of both newly inserted node and maxFibnode and make the highest hashvalue one as max.
//System.out.println("after "+maxFibnode.keyword);
}
total_nodes++;//After the insertion the total numbers of nodes are increased by 1
}
public FibNode maxnode_remove()//This function is used to remove the maxFibnode.
{
FibNode node = maxFibnode;
if(isEmpty(node)!=0)//if maxFibnode exists
{
FibNode temp_child;
FibNode node_child = node.child;//child of max
int num_of_children = node.degree;//degree of max
while (num_of_children > 0) //The children are removed one by one from the maxnode and are added to the root list of heap.
{
temp_child = node_child.right;//the right sibling of node
left_right_merge(node_child);// //This function is used to connect siblings of node_child together before adding it to the root list of heap
sibling_link(maxFibnode,node_child);//Insert node_child between node max and node right of max
node_child.parent = null;//parent of node_child is set to null because it is added to the root list of heap
node_child = temp_child;//
num_of_children--;//decrease number of children
}
left_right_merge(node);// remove node from root list of heap
if (node != node.right)
{
maxFibnode = node.right;
Merge_Pairwise();//after removing max node we call function degreewiseMerge() on remaining nodes (max siblings)
}
else
{
maxFibnode = null;
}
total_nodes--;
return node;
}
return null;
}
public void Nodecut(FibNode p, FibNode gp)
{
//This function cuts the node p from gp, and decreases the degree of node gp
left_right_merge(p);//This function is used to remove the input node by connecting its siblings together
gp.degree--;//gp lost 1 child p , decrease degree of gp
if (gp.degree == 0) //if it is a leaf
{
gp.child = null;
}
if (gp.child == p) //if p was pointed to as gp.child change it
{
gp.child = p.right;//make right sibling of p as gp.child due to removal of node p
}
sibling_link(maxFibnode,p);//insert p as right sibling of maxFibnode
p.childcut_value = false;//since p is just added to root list of heap its childcut value is set to false
p.parent = null;//parent of p is set to null
}
public void Node_CascadingCut(FibNode newnode)//This function is used to perform cascading cut based on the childcut _value.
{
FibNode node_parent = newnode.parent;
//if there is a parent
// if (node_parent != null)
if(isEmpty(node_parent)!=0)
//If the newnode has parent then perform cascading cut based on childcut value up to the root.
{
/* If childcut value of newnode is true ( it has previously lost a child)
then perform Nodecut() on it and perform Cascading cut on its parent
*/
if (newnode.childcut_value)
{
Nodecut(newnode, node_parent);
// cut its parent as well
Node_CascadingCut(node_parent);
}
else
// If childcut value of newnode is false (it did not lose child before this) set its childcut_value to true.
{
newnode.childcut_value = true;
}
}
}
//This function is used to make node newchild as child of the node newparent. This function is useful in Merge_Pairwise()
public void child_create(FibNode newchild, FibNode newparent)
{
left_right_merge(newchild);//This function is used to remove the input node by connecting its siblings together
newchild.parent = newparent;// make newchild a child of node newparent
if (newparent.child != null)
{
sibling_link(newparent.child,newchild);//link this node with other children of its parent
}
else //if parent of newchild is null
{
newparent.child = newchild;
newchild.left = newchild;
newchild.right = newchild;
}
newparent.degree++;//due to insertion of a node increase degree of parent by 1
newchild.childcut_value = false;//assign false to childcut value of newly added child
}
public void Merge_Pairwise()//This function performs degree wise merge after removing maxFibnode
{
int num_of_root = 0;// initial number of roots 0
//int table_degree_size =50;
int table_degree_size =
((int) Math.floor(Math.log(total_nodes) * matvariable)) + 1;// table to store degrees , formula given in Cormen
FibNode node = maxFibnode;
List<FibNode> table_degree =new ArrayList<FibNode>(table_degree_size);//to store the removed nodes
for (int i = 0; i < table_degree_size; i++)
{
table_degree.add(null);// table where degrees are stored is initialized
}
if (node != null) //count all the nodes until no node exists
{
node = node.right;
num_of_root++;
while (node != maxFibnode)
{
num_of_root++;
node = node.right;
}
}
while (num_of_root > 0)
{// execute for all nodes in root list
FibNode next = node.right;
int d = node.degree;
for (;;)
{
FibNode table_node = table_degree.get(d);//use method to get value of degree
if (table_node == null)
{
break;//if no nodes left in table
}
if (table_node.hashvalue>node.hashvalue)
//Compare the hashvalue and make one of the nodes a child of the other. For this make table_node as parent and node as child after swapping(if swapping is needed)
{
FibNode temp = table_node;
table_node = node;
node = temp;
}
/*
System.out.println("before tablenode"+table_node.keyword);
System.out.println("before node"+node.keyword);
System.out.println("after tablenode"+table_node.keyword);
System.out.println("after node"+node.keyword);
*/
child_create(table_node, node);//make table_node the child of node as node.hashvalue is greater
table_degree.set(d, null);//degree is set to null after combining
d++;
}
table_degree.set(d, node);//store the new degree in the respective postion
num_of_root--;//go through the remaining list
node = next;
}
maxFibnode = null;
for (int i = 0; i < table_degree_size; i++)// combine nodes of same degree
{
FibNode node_nxt = table_degree.get(i);
if (node_nxt == null) //if node doesnt exist
{
continue;
}
if (isEmpty(maxFibnode)==0)//if maxFibnode is null
{
maxFibnode = node_nxt;
}
else
//if maxFibnode is not null
{
left_right_merge(node_nxt);//remove node_nxt from root list.
sibling_link(maxFibnode,node_nxt);//add node_nxt root list
maxFibnode=compare_hash(node_nxt,maxFibnode);//Check if node_nxt is new maximum
/*
if (node_nxt.hashvalue > maxFibnode.hashvalue)
{
maxFibnode = node_nxt;
}
*/
}
}
}
}