Skip to content

Commit

Permalink
ADD: 29_priority_queue
Browse files Browse the repository at this point in the history
  • Loading branch information
lixingliang committed Mar 15, 2019
1 parent 1a16bc2 commit 7612aa0
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 0 deletions.
22 changes: 22 additions & 0 deletions go/29_priority_queue/heap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package pqueue

func adjustHeap(src []Node, start, end int) {
if start >= end {
return
}

// 只需要保证优先级最高的节点在 src[1] 的位置即可
for i := end / 2; i >= start; i-- {
high := i
if src[high].priority < src[2*i].priority {
high = 2 * i
}
if 2*i+1 <= end && src[high].priority < src[2*i+1].priority {
high = 2*i + 1
}
if high == i {
continue
}
src[high], src[i] = src[i], src[high]
}
}
14 changes: 14 additions & 0 deletions go/29_priority_queue/heap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pqueue

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_AdjustHeap(t *testing.T) {
list := []Node{Node{0, 0}, Node{1, 1}, Node{2, 2}, Node{3, 3}, Node{4, 1}, Node{6, 6}}

adjustHeap(list, 1, len(list)-1)
assert.Equal(t, 6, list[1].value)
}
62 changes: 62 additions & 0 deletions go/29_priority_queue/priority_queue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package pqueue

// Node 队列节点
type Node struct {
value int
priority int
}

// PQueue priority queue
type PQueue struct {
heap []Node

capacity int
used int
}

// NewPriorityQueue new
func NewPriorityQueue(capacity int) PQueue {
return PQueue{
heap: make([]Node, capacity+1, capacity+1),
capacity: capacity,
used: 0,
}
}

// Push 入队
func (q *PQueue) Push(node Node) {

if q.used > q.capacity {
// 队列已满
return
}
q.used++
q.heap[q.used] = node
// 堆化可以放在 Pop 中
// adjustHeap(q.heap, 1, q.used)
}

// Pop 出队列
func (q *PQueue) Pop() Node {
if q.used == 0 {
return Node{-1, -1}
}
// 先堆化, 再取堆顶元素
adjustHeap(q.heap, 1, q.used)
node := q.heap[1]

q.heap[1] = q.heap[q.used]
q.used--

return node
}

// Top 获取队列顶部元素
func (q *PQueue) Top() Node {
if q.used == 0 {
return Node{-1, -1}
}

adjustHeap(q.heap, 1, q.used)
return q.heap[1]
}
74 changes: 74 additions & 0 deletions go/29_priority_queue/priority_queue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package pqueue

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_Push(t *testing.T) {
queue := NewPriorityQueue(100)

queue.Push(Node{0, 1})
assert.Equal(t, 0, queue.Top().value)

queue.Push(Node{3, 1})
assert.Equal(t, 0, queue.Top().value)

queue.Push(Node{3, 2})
assert.Equal(t, 3, queue.Top().value)

queue.Push(Node{6, 6})
assert.Equal(t, 6, queue.Top().value)

queue.Push(Node{12, 5})
assert.Equal(t, 6, queue.Top().value)

queue.Push(Node{13, 8})
assert.Equal(t, 13, queue.Top().value)
}

func Test_PushPop(t *testing.T) {
queue := NewPriorityQueue(100)

queue.Push(Node{0, 1})
queue.Push(Node{3, 1})
queue.Push(Node{3, 2})
queue.Push(Node{6, 6})
queue.Push(Node{12, 5})
queue.Push(Node{13, 8})
assert.Equal(t, 13, queue.Top().value)

assert.Equal(t, 13, queue.Pop().value)
assert.Equal(t, 6, queue.Pop().value)
assert.Equal(t, 12, queue.Top().value)
assert.Equal(t, 12, queue.Pop().value)

queue.Push(Node{24, 8})
assert.Equal(t, 24, queue.Top().value)
}

// 无法保证入队顺序和出队顺序的一致性
// func Test_PushPop_Equal(t *testing.T) {
// queue := NewPriorityQueue(9)

// queue.Push(Node{0, 1}) // 8
// queue.Push(Node{3, 1}) // 9
// queue.Push(Node{3, 2}) // 3
// queue.Push(Node{6, 2}) // 4
// queue.Push(Node{11, 3}) // 2
// queue.Push(Node{12, 2}) // 5
// queue.Push(Node{13, 2}) // 6
// queue.Push(Node{19, 5}) // 1
// queue.Push(Node{17, 2}) // 7

// assert.Equal(t, 19, queue.Pop().value)
// assert.Equal(t, 11, queue.Pop().value)
// assert.Equal(t, 3, queue.Pop().value)
// assert.Equal(t, 6, queue.Pop().value)
// assert.Equal(t, 12, queue.Pop().value)
// assert.Equal(t, 13, queue.Pop().value)
// assert.Equal(t, 17, queue.Pop().value)
// assert.Equal(t, 0, queue.Pop().value)
// assert.Equal(t, 3, queue.Pop().value)
// }
3 changes: 3 additions & 0 deletions go/29_priority_queue/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

## TODO
- 该实现方式不能保证 相同优先级的元素在出队列时 和入队列的顺序是一致的

0 comments on commit 7612aa0

Please sign in to comment.