Skip to content

Commit 7612aa0

Browse files
author
lixingliang
committed
ADD: 29_priority_queue
1 parent 1a16bc2 commit 7612aa0

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed

go/29_priority_queue/heap.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package pqueue
2+
3+
func adjustHeap(src []Node, start, end int) {
4+
if start >= end {
5+
return
6+
}
7+
8+
// 只需要保证优先级最高的节点在 src[1] 的位置即可
9+
for i := end / 2; i >= start; i-- {
10+
high := i
11+
if src[high].priority < src[2*i].priority {
12+
high = 2 * i
13+
}
14+
if 2*i+1 <= end && src[high].priority < src[2*i+1].priority {
15+
high = 2*i + 1
16+
}
17+
if high == i {
18+
continue
19+
}
20+
src[high], src[i] = src[i], src[high]
21+
}
22+
}

go/29_priority_queue/heap_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package pqueue
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func Test_AdjustHeap(t *testing.T) {
10+
list := []Node{Node{0, 0}, Node{1, 1}, Node{2, 2}, Node{3, 3}, Node{4, 1}, Node{6, 6}}
11+
12+
adjustHeap(list, 1, len(list)-1)
13+
assert.Equal(t, 6, list[1].value)
14+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package pqueue
2+
3+
// Node 队列节点
4+
type Node struct {
5+
value int
6+
priority int
7+
}
8+
9+
// PQueue priority queue
10+
type PQueue struct {
11+
heap []Node
12+
13+
capacity int
14+
used int
15+
}
16+
17+
// NewPriorityQueue new
18+
func NewPriorityQueue(capacity int) PQueue {
19+
return PQueue{
20+
heap: make([]Node, capacity+1, capacity+1),
21+
capacity: capacity,
22+
used: 0,
23+
}
24+
}
25+
26+
// Push 入队
27+
func (q *PQueue) Push(node Node) {
28+
29+
if q.used > q.capacity {
30+
// 队列已满
31+
return
32+
}
33+
q.used++
34+
q.heap[q.used] = node
35+
// 堆化可以放在 Pop 中
36+
// adjustHeap(q.heap, 1, q.used)
37+
}
38+
39+
// Pop 出队列
40+
func (q *PQueue) Pop() Node {
41+
if q.used == 0 {
42+
return Node{-1, -1}
43+
}
44+
// 先堆化, 再取堆顶元素
45+
adjustHeap(q.heap, 1, q.used)
46+
node := q.heap[1]
47+
48+
q.heap[1] = q.heap[q.used]
49+
q.used--
50+
51+
return node
52+
}
53+
54+
// Top 获取队列顶部元素
55+
func (q *PQueue) Top() Node {
56+
if q.used == 0 {
57+
return Node{-1, -1}
58+
}
59+
60+
adjustHeap(q.heap, 1, q.used)
61+
return q.heap[1]
62+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package pqueue
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func Test_Push(t *testing.T) {
10+
queue := NewPriorityQueue(100)
11+
12+
queue.Push(Node{0, 1})
13+
assert.Equal(t, 0, queue.Top().value)
14+
15+
queue.Push(Node{3, 1})
16+
assert.Equal(t, 0, queue.Top().value)
17+
18+
queue.Push(Node{3, 2})
19+
assert.Equal(t, 3, queue.Top().value)
20+
21+
queue.Push(Node{6, 6})
22+
assert.Equal(t, 6, queue.Top().value)
23+
24+
queue.Push(Node{12, 5})
25+
assert.Equal(t, 6, queue.Top().value)
26+
27+
queue.Push(Node{13, 8})
28+
assert.Equal(t, 13, queue.Top().value)
29+
}
30+
31+
func Test_PushPop(t *testing.T) {
32+
queue := NewPriorityQueue(100)
33+
34+
queue.Push(Node{0, 1})
35+
queue.Push(Node{3, 1})
36+
queue.Push(Node{3, 2})
37+
queue.Push(Node{6, 6})
38+
queue.Push(Node{12, 5})
39+
queue.Push(Node{13, 8})
40+
assert.Equal(t, 13, queue.Top().value)
41+
42+
assert.Equal(t, 13, queue.Pop().value)
43+
assert.Equal(t, 6, queue.Pop().value)
44+
assert.Equal(t, 12, queue.Top().value)
45+
assert.Equal(t, 12, queue.Pop().value)
46+
47+
queue.Push(Node{24, 8})
48+
assert.Equal(t, 24, queue.Top().value)
49+
}
50+
51+
// 无法保证入队顺序和出队顺序的一致性
52+
// func Test_PushPop_Equal(t *testing.T) {
53+
// queue := NewPriorityQueue(9)
54+
55+
// queue.Push(Node{0, 1}) // 8
56+
// queue.Push(Node{3, 1}) // 9
57+
// queue.Push(Node{3, 2}) // 3
58+
// queue.Push(Node{6, 2}) // 4
59+
// queue.Push(Node{11, 3}) // 2
60+
// queue.Push(Node{12, 2}) // 5
61+
// queue.Push(Node{13, 2}) // 6
62+
// queue.Push(Node{19, 5}) // 1
63+
// queue.Push(Node{17, 2}) // 7
64+
65+
// assert.Equal(t, 19, queue.Pop().value)
66+
// assert.Equal(t, 11, queue.Pop().value)
67+
// assert.Equal(t, 3, queue.Pop().value)
68+
// assert.Equal(t, 6, queue.Pop().value)
69+
// assert.Equal(t, 12, queue.Pop().value)
70+
// assert.Equal(t, 13, queue.Pop().value)
71+
// assert.Equal(t, 17, queue.Pop().value)
72+
// assert.Equal(t, 0, queue.Pop().value)
73+
// assert.Equal(t, 3, queue.Pop().value)
74+
// }

go/29_priority_queue/readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
## TODO
3+
- 该实现方式不能保证 相同优先级的元素在出队列时 和入队列的顺序是一致的

0 commit comments

Comments
 (0)