-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbinomheap.go
129 lines (101 loc) · 3.47 KB
/
binomheap.go
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
package BinomialHeap
import "fmt"
/*
This is the struct that serves as entrypoint to the heap and implements the priority queue interface.
*/
type BinomialHeap struct {
// In binomial heaps, there are no such thing as global root. It is a collection of trees, called a "forest"
// forest_head points to the head of a descending "order"-ordered linked list. The linking mechanism is implemented
// in "BinomialHeapNode"
forest_head *BinomialHeapNode
// Amount of elements in the heap.
size int
}
func NewBinomialHeap() *BinomialHeap {
return &BinomialHeap {
forest_head: nil,
size: 0,
}
}
/*
Insertion function that satisfies priorityqueue interface. Head over to "insert" for the actual insertion.
*/
func (bh* BinomialHeap) Insert(value int) {
bh.size += 1
newnode := newBinomialHeapNode(value)
bh.insert(newnode)
}
/*
Popping mechanism is as follows;
* Get the minimum node among the forest heads
* Remove that node among forest heads.
* Insert all of the minimum node's children to the queue again.
*/
func (bh* BinomialHeap) Pop() int {
// Assume the queue is not empty.
bh.size -= 1
minnode := getMinimumNode(bh.forest_head)
removeFromLinkedList(&bh.forest_head, minnode)
for _, child := range nodeIterator(minnode.children_head) {
removeFromLinkedList(&minnode.children_head, child)
bh.insert(child)
}
return minnode.value
}
/*
Return the minimum valued node, but do not remove.
This operation can be made O(1) trivially. Do it.
*/
func (bh* BinomialHeap) Peek() int {
return getMinimumNode(bh.forest_head).value
}
/*
Return the element count in the heap.
*/
func (bh* BinomialHeap) Size() int {
return bh.size
}
/*
Merge operations is akin to "Pop";
* For every forest head present on the other heap:
* remove that node from the other heap
* insert this node to this heap using the insertion procedure.
*/
func (bh* BinomialHeap) Merge(other *BinomialHeap) {
bh.size += other.size
for _, child := range nodeIterator(other.forest_head) {
removeFromLinkedList(&other.forest_head, child)
bh.insert(child)
}
}
/*
Here is the actual magic. Suppose that we are attempting to insert a node with order N
* If there is already a node exists in the forest with order N
* Link these two nodes, yielding a node with order N+1 (read "linkNodes" for details)
* Re-insert this newly made node
* If there is not, simply put this node somewhere in the linked list of forest heads.
Recall that, there cannot exists two nodes with the same rank on a linked list (they can exist on different ones though)
Linking operation is done to address this, but this same conflict may happend for the node with order N+1.
This means we should insert and reinsert until we can make an insertion order-conflict-free.
*/
func (bh *BinomialHeap) insert(newnode *BinomialHeapNode) {
srnode := getNodeWithOrder(bh.forest_head, newnode.order)
if srnode == nil {
insertIntoLinkedList(&bh.forest_head, newnode)
} else {
removeFromLinkedList(&bh.forest_head, srnode)
linkednode := linkNodes(srnode, newnode)
bh.insert(linkednode)
}
}
/*
Print the elements of the heap in a depth-first fashion.
*/
func (bh *BinomialHeap) print() {
if bh.forest_head == nil {
fmt.Print("heap is empty.")
}
for _, node := range nodeIterator(bh.forest_head) {
node.print_recursive(0)
}
}