Skip to content

Commit d7b108b

Browse files
erjiaqingtheodesp
authored andcommitted
Rank Pairing Heap Implementation (#32)
* impl. rank paring heap * update meld * support Adjust and Delete * update test * rename type & add test
1 parent ac088a9 commit d7b108b

File tree

3 files changed

+566
-0
lines changed

3 files changed

+566
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/theodesp/go-heaps"
7+
rpheap "github.com/theodesp/go-heaps/rank_pairing"
8+
)
9+
10+
func main() {
11+
heap := rpheap.New()
12+
heap.Insert(Int(4))
13+
heap.Insert(Int(3))
14+
heap.Insert(Int(2))
15+
heap.Insert(Int(5))
16+
17+
fmt.Println(heap.DeleteMin()) // 2
18+
fmt.Println(heap.DeleteMin()) // 3
19+
fmt.Println(heap.DeleteMin()) // 4
20+
fmt.Println(heap.DeleteMin()) // 5
21+
22+
heap1 := rpheap.New()
23+
heap2 := rpheap.New()
24+
heap1.Insert(Int(2))
25+
heap1.Insert(Int(8))
26+
heap1.Insert(Int(5))
27+
heap1.Insert(Int(7))
28+
heap2.Insert(Int(4))
29+
heap2.Insert(Int(9))
30+
heap2.Insert(Int(6))
31+
32+
heap1.Meld(heap2)
33+
34+
fmt.Println(heap1.DeleteMin()) // 2
35+
fmt.Println(heap1.DeleteMin()) // 4
36+
fmt.Println(heap1.DeleteMin()) // 5
37+
//...
38+
}
39+
40+
func Int(value int) go_heaps.Integer {
41+
return go_heaps.Integer(value)
42+
}

rank_pairing/rank_pairing_heap.go

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
package rank_paring
2+
3+
import (
4+
"fmt"
5+
6+
heap "github.com/theodesp/go-heaps"
7+
)
8+
9+
type node struct {
10+
item heap.Item
11+
left, next, parent *node
12+
rank int
13+
}
14+
15+
// RPHeap is an implementation of a rank Pairing Heap.
16+
// The zero value for RPHeap Root is an empty Heap.
17+
type RPHeap struct {
18+
head *node
19+
size int
20+
}
21+
22+
type nInf struct{}
23+
24+
func (a nInf) Compare(b heap.Item) int {
25+
switch b.(type) {
26+
case nInf:
27+
return 0
28+
default:
29+
return -1
30+
}
31+
}
32+
33+
// wrap compare function to support nInf (negative inf) type
34+
func compare(a, b heap.Item) int {
35+
switch b.(type) {
36+
case nInf:
37+
switch a.(type) {
38+
case nInf:
39+
return 0
40+
default:
41+
return 1
42+
}
43+
default:
44+
return a.Compare(b)
45+
}
46+
}
47+
48+
// Init initializes or clears the rankPairingHeap
49+
func (p *RPHeap) Init() *RPHeap {
50+
p.head = &node{}
51+
p.size = 0
52+
return p
53+
}
54+
55+
// New returns an initialized rankPairingHeap.
56+
func New() *RPHeap { return new(RPHeap).Init() }
57+
58+
// FindMin returns the value of root
59+
// Complexity: O(1)
60+
func (r *RPHeap) FindMin() heap.Item {
61+
return r.head.item
62+
}
63+
64+
// Insert the value val into the heap and return it
65+
// Complexity: O(1)
66+
func (r *RPHeap) Insert(val heap.Item) heap.Item {
67+
ptr := &node{
68+
item: val,
69+
}
70+
r.insertRoot(ptr)
71+
r.size++
72+
return val
73+
}
74+
75+
// DeleteMin removes the top most value from the rankPairingHeap and returns it
76+
// Complexity: O(log n)
77+
func (r *RPHeap) DeleteMin() heap.Item {
78+
bucket := make([]*node, r.maxBucketSize())
79+
ret := r.head.item
80+
// an empty heap will panic here
81+
if ret == nil {
82+
return nil
83+
}
84+
r.size--
85+
for ptr := r.head.left; ptr != nil; {
86+
nextPtr := ptr.next
87+
ptr.next = nil
88+
ptr.parent = nil
89+
bucket = multiPass(bucket, ptr)
90+
ptr = nextPtr
91+
}
92+
for ptr := r.head.next; ptr != r.head; {
93+
nextPtr := ptr.next
94+
ptr.next = nil
95+
bucket = multiPass(bucket, ptr)
96+
ptr = nextPtr
97+
}
98+
r.head = &node{}
99+
for _, ptr := range bucket {
100+
if ptr != nil {
101+
r.insertRoot(ptr)
102+
}
103+
}
104+
return ret
105+
}
106+
107+
// Clear the whole rankPairingHeap
108+
func (r *RPHeap) Clear() {
109+
r.Init()
110+
}
111+
112+
// Merge a rankPairingHeap r0 into a heap r, then clear r0
113+
// Complexity: O(1)
114+
func (r *RPHeap) Meld(a heap.Interface) heap.Interface {
115+
switch a.(type) {
116+
case *RPHeap:
117+
default:
118+
panic(fmt.Sprintf("unexpected type %T", a))
119+
}
120+
r0 := a.(*RPHeap)
121+
if r.head.item == nil {
122+
r.head = r0.head
123+
r.size = r0.size
124+
r0.Clear()
125+
return r
126+
}
127+
if r0.head.item == nil {
128+
return r
129+
}
130+
if compare(r.head.item, r0.head.item) < 0 {
131+
mergeRes := merge(r, r0)
132+
r0.Clear()
133+
return mergeRes
134+
} else {
135+
mergeRes := merge(r0, r)
136+
r0.Clear()
137+
return mergeRes
138+
}
139+
}
140+
141+
// Size returns the size of the RPHeap
142+
func (r *RPHeap) Size() int {
143+
return r.size
144+
}
145+
146+
// Adjust the value of an item, since we have to find the item
147+
// Complexity is O(n)
148+
func (r *RPHeap) Adjust(old, new heap.Item) heap.Item {
149+
ptr := r.find(r.head, old)
150+
if ptr == nil {
151+
return nil
152+
}
153+
if compare(ptr.item, new) < 0 {
154+
r.decrease(ptr, nInf{})
155+
r.DeleteMin()
156+
r.Insert(new)
157+
} else {
158+
r.decrease(ptr, new)
159+
}
160+
return new
161+
}
162+
163+
// Delete an item from the heap
164+
// Complexity is O(n)
165+
func (r *RPHeap) Delete(val heap.Item) heap.Item {
166+
ptr := r.find(r.head, val)
167+
if ptr == nil {
168+
return nil
169+
}
170+
if ptr == r.head {
171+
return r.DeleteMin()
172+
}
173+
r.decrease(ptr, nInf{})
174+
r.DeleteMin()
175+
return val
176+
}
177+
178+
// Decrease the value of an item
179+
// Complexity is O(log n)
180+
func (r *RPHeap) decrease(ptr *node, val heap.Item) {
181+
if compare(val, ptr.item) < 0 {
182+
ptr.item = val
183+
}
184+
if ptr == r.head {
185+
return
186+
}
187+
if ptr.parent == nil {
188+
if compare(ptr.item, r.head.item) < 0 {
189+
r.head = ptr
190+
}
191+
} else {
192+
parent := ptr.parent
193+
if ptr == parent.left {
194+
parent.left = ptr.next
195+
if parent.left != nil {
196+
parent.left.parent = parent
197+
}
198+
} else {
199+
parent.next = ptr.next
200+
if parent.next != nil {
201+
parent.next.parent = parent
202+
}
203+
}
204+
ptr.next, ptr.parent = nil, nil
205+
if ptr.left != nil {
206+
ptr.rank = ptr.left.rank + 1
207+
} else {
208+
ptr.rank = 0
209+
}
210+
r.insertRoot(ptr)
211+
if parent.parent == nil {
212+
parent.rank = getrank(parent.left) + 1
213+
} else {
214+
for parent.parent != nil {
215+
leftrank := getrank(parent.left)
216+
nextrank := getrank(parent.next)
217+
newrank := leftrank + 1
218+
if leftrank != nextrank {
219+
if leftrank > nextrank {
220+
newrank = leftrank
221+
} else {
222+
newrank = nextrank
223+
}
224+
}
225+
if newrank >= parent.rank {
226+
break
227+
}
228+
parent.rank = newrank
229+
parent = parent.parent
230+
}
231+
}
232+
}
233+
}
234+
235+
// Find the pointer to an item
236+
// Complexity: O(n)
237+
func (r *RPHeap) find(root *node, val heap.Item) *node {
238+
if root == nil {
239+
return nil
240+
} else if compare(root.item, val) == 0 {
241+
return root
242+
} else {
243+
if leftfind := r.find(root.left, val); leftfind != nil {
244+
return leftfind
245+
}
246+
for ptr := root.next; ptr != nil && ptr != root; ptr = ptr.next {
247+
if compare(ptr.item, val) == 0 {
248+
return ptr
249+
}
250+
if leftfind := r.find(ptr.left, val); leftfind != nil {
251+
return leftfind
252+
}
253+
}
254+
}
255+
return nil
256+
}
257+
258+
func getrank(root *node) int {
259+
if root == nil {
260+
return -1
261+
}
262+
return root.rank
263+
}
264+
265+
func merge(r0, r1 *RPHeap) *RPHeap {
266+
if r1.Size() == 1 {
267+
ptr := r1.head
268+
ptr.next, ptr.parent, ptr.left, ptr.rank = nil, nil, nil, 0
269+
r0.insertRoot(ptr)
270+
r0.size++
271+
return &RPHeap{
272+
head: r0.head,
273+
size: r0.size,
274+
}
275+
} else if r0.Size() == 1 {
276+
return merge(r1, r0)
277+
}
278+
r0.head.next, r1.head.next = r1.head.next, r0.head.next
279+
r0.size += r1.size
280+
return &RPHeap{
281+
head: r0.head,
282+
size: r0.size,
283+
}
284+
}
285+
286+
func (r *RPHeap) maxBucketSize() int {
287+
bit, cnt := 1, r.size
288+
for cnt > 1 {
289+
cnt /= 2
290+
bit++
291+
}
292+
return bit + 1
293+
}
294+
295+
func (r *RPHeap) insertRoot(ptr *node) {
296+
if r.head.item == nil {
297+
r.head = ptr
298+
ptr.next = ptr
299+
} else {
300+
ptr.next = r.head.next
301+
r.head.next = ptr
302+
if compare(ptr.item, r.head.item) < 0 {
303+
r.head = ptr
304+
}
305+
}
306+
}
307+
308+
func multiPass(bucket []*node, ptr *node) []*node {
309+
for bucket[ptr.rank] != nil {
310+
rank := ptr.rank
311+
ptr = link(ptr, bucket[rank])
312+
bucket[rank] = nil
313+
}
314+
bucket[ptr.rank] = ptr
315+
return bucket
316+
}
317+
318+
func link(left *node, right *node) *node {
319+
if right == nil {
320+
return left
321+
}
322+
var winner, loser *node
323+
if compare(right.item, left.item) < 0 {
324+
winner = right
325+
loser = left
326+
} else {
327+
winner = left
328+
loser = right
329+
}
330+
loser.parent = winner
331+
if winner.left != nil {
332+
loser.next = winner.left
333+
loser.next.parent = loser
334+
}
335+
winner.left = loser
336+
winner.rank = loser.rank + 1
337+
return winner
338+
}

0 commit comments

Comments
 (0)