From b2d62bb55a311d176a9020a967e06339ad56414b Mon Sep 17 00:00:00 2001 From: huangsimin Date: Thu, 31 Jan 2019 18:39:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84priority=5Fqueue=E4=B8=AD,=20?= =?UTF-8?q?TODO:=20=E7=BB=A7=E7=BB=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- priority_queue/priority_list.go | 41 ------ priority_queue/priority_queue.go | 138 ++++++++++++++++++ ...ty_list_test.go => priority_queue_test.go} | 34 ++++- 3 files changed, 164 insertions(+), 49 deletions(-) delete mode 100644 priority_queue/priority_list.go create mode 100644 priority_queue/priority_queue.go rename priority_queue/{priority_list_test.go => priority_queue_test.go} (60%) diff --git a/priority_queue/priority_list.go b/priority_queue/priority_list.go deleted file mode 100644 index 55d31e2..0000000 --- a/priority_queue/priority_list.go +++ /dev/null @@ -1,41 +0,0 @@ -package plist - -import ( - "github.com/emirpasic/gods/lists/arraylist" - "github.com/emirpasic/gods/utils" -) - -// PriorityQueue 优先队列 -type PriorityQueue struct { - array arraylist.List - comparator utils.Comparator - isSorted bool -} - -// NewWithInt compare use int -func NewWithInt() *PriorityQueue { - p := new(PriorityQueue) - p.comparator = func(a, b interface{}) int { - if a.(int) > b.(int) { - return 1 - } - return -1 - } - return p -} - -func (pq *PriorityQueue) Push(v interface{}) { - pq.array.Add(v) - if pq.isSorted { - pq.isSorted = false - } -} - -func (pq *PriorityQueue) Values() []interface{} { - if !pq.isSorted { - pq.array.Sort(pq.comparator) - pq.isSorted = true - - } - return pq.array.Values() -} diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go new file mode 100644 index 0000000..8b42426 --- /dev/null +++ b/priority_queue/priority_queue.go @@ -0,0 +1,138 @@ +package plist + +import ( + "github.com/emirpasic/gods/utils" +) + +// PriorityQueue 优先队列 适合数据量不大, 加索引 +type PriorityQueue struct { + left, right, mid int + datas []interface{} + size int + comparator utils.Comparator + isLeftSorted bool + isRightSorted bool +} + +// NewWithInt compare use int +func NewWithInt() *PriorityQueue { + p := new(PriorityQueue) + p.datas = make([]interface{}, 8) + p.comparator = func(a, b interface{}) int { + if a.(int) > b.(int) { + return 1 + } + return -1 + } + return p +} + +func (pq *PriorityQueue) reArrange() { + +} + +func (pq *PriorityQueue) reMakeMemory() { + + var incSize int + if pq.size >= 1048 { + incSize = pq.size / 2 + } else { + incSize = pq.size + } + + capacity := pq.size + incSize + temp := make([]interface{}, capacity) + + mid := capacity / 2 + left := mid - pq.size/2 + + copy(temp[left:], pq.datas[pq.left:pq.right]) + pq.datas = temp + pq.left = left + pq.mid = mid + pq.right = pq.size + pq.left + +} + +func (pq *PriorityQueue) Push(v interface{}) { + + if pq.size == 0 { + pq.mid = len(pq.datas) / 2 + pq.left = pq.mid + pq.right = pq.mid + 1 + + pq.datas[pq.mid] = v + + } else { + + if pq.comparator(v, pq.datas[pq.mid]) > 0 { + + if pq.right >= len(pq.datas) { + // 重建 datas + pq.reMakeMemory() + } + + pq.datas[pq.right] = v + pq.right++ + + if pq.isRightSorted { + pq.isRightSorted = false + } + + } else { + + if pq.left-1 < 0 { + // 重建 datas + pq.reMakeMemory() + } + pq.left-- + pq.datas[pq.left] = v + + if pq.isLeftSorted { + pq.isLeftSorted = false + } + } + } + pq.size++ +} + +func (pq *PriorityQueue) PopTop() (interface{}, bool) { + + return v, isok +} + +func (pq *PriorityQueue) PopBottom() (interface{}, bool) { + + return v, isok +} + +func (pq *PriorityQueue) Top() (interface{}, bool) { + return pq.Get(0) +} + +func (pq *PriorityQueue) Bottom() (interface{}, bool) { + return pq.Get(pq.right - 1) +} + +func (pq *PriorityQueue) Get(index int) (interface{}, bool) { + if index < pq.size { + return pq.Values()[index], true + } + return nil, false +} + +func (pq *PriorityQueue) Values() []interface{} { + values := pq.datas[pq.left:pq.right] + + if !pq.isLeftSorted { + utils.Sort(values[0:pq.size/2], pq.comparator) + pq.isLeftSorted = true + } + + if !pq.isRightSorted { + utils.Sort(values[pq.size/2:], pq.comparator) + pq.isRightSorted = true + } + + return values +} diff --git a/priority_queue/priority_list_test.go b/priority_queue/priority_queue_test.go similarity index 60% rename from priority_queue/priority_list_test.go rename to priority_queue/priority_queue_test.go index 151d826..f65422a 100644 --- a/priority_queue/priority_list_test.go +++ b/priority_queue/priority_queue_test.go @@ -3,6 +3,8 @@ package plist import ( "testing" + "github.com/emirpasic/gods/utils" + "github.com/Pallinder/go-randomdata" "github.com/emirpasic/gods/trees/binaryheap" @@ -11,23 +13,25 @@ import ( func TestPriorityQueue(t *testing.T) { p := NewWithInt() - for i := 0; i < 100; i++ { + for i := 0; i < 20; i++ { p.Push(randomdata.Number(0, 10000)) - if i%100 == 99 { - p.Values() - } } t.Error(p.Values()) + t.Error(p.datas, p.size, len(p.Values())) + + for _, idx := range []int{5, 0, 21, 19} { + t.Error(p.Get(idx)) + } + } -func BenchmarkPriorityQueue(b *testing.B) { - +func BenchmarkPriorityQueue10(b *testing.B) { p := NewWithInt() for i := 0; i < b.N; i++ { - p.Push(randomdata.Number(0, 10000)) - if i%1000 == 999 { + p.Push(randomdata.Number(0, 100000)) + if i%10 == 0 { p.Values() } } @@ -35,6 +39,20 @@ func BenchmarkPriorityQueue(b *testing.B) { // t.Error(p.String()) } +func TestHeap(t *testing.T) { + heap := binaryheap.NewWithIntComparator() + + for i := 0; i < 10; i++ { + heap.Push(randomdata.Number(0, 1000)) + } + + t.Error(heap.Peek()) + t.Error(heap.Values()) + + utils.Sort(heap.Values(), utils.IntComparator) + +} + func BenchmarkList_InsertValues123(b *testing.B) { a := func(v1, v2 interface{}) int { if v1.(int) > v2.(int) {