diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go index 59d133d..6c95710 100644 --- a/priority_queue/priority_queue.go +++ b/priority_queue/priority_queue.go @@ -1,24 +1,36 @@ package plist import ( - "log" - + "github.com/davecgh/go-spew/spew" "github.com/emirpasic/gods/utils" ) // PriorityQueue 优先队列 适合数据量不大, 加索引 type PriorityQueue struct { - left, right, mid int - datas []interface{} - size int - comparator utils.Comparator - isSorted bool + index *Index + indexlimit int + node *Node + size int + comparator utils.Comparator +} + +type Index struct { + node *Node + next *Index + nlen int +} + +type Node struct { + value interface{} + + prev *Node + next *Node } // NewWithInt compare use int func NewWithInt() *PriorityQueue { p := new(PriorityQueue) - p.datas = make([]interface{}, 8) + p.indexlimit = 10 p.comparator = func(a, b interface{}) int { if a.(int) > b.(int) { return 1 @@ -28,174 +40,110 @@ func NewWithInt() *PriorityQueue { 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 - 1 - - x := pq.datas - copy(temp[left+1:], pq.datas[pq.left+1:pq.right]) - pq.datas = temp - pq.left = left - pq.mid = mid - pq.right = pq.size + pq.left - - log.Println(x, pq.datas, pq.left, pq.right) - -} - -func (pq *PriorityQueue) search(v interface{}) int { - // left := pq.left - // right := pq.right - - data := pq.datas[pq.left+1 : pq.right] - left := 0 - mid := 0 - right := len(data) - - for left < right-1 { - mid = (left + right) / 2 // 4 10 7 10 8 10 9 10 | 4 10 4 7 4 5 - if pq.comparator(v, data[mid]) > 0 { - left = mid +func (pq *PriorityQueue) String() string { + content := "" + for cur := pq.node; cur != nil; cur = cur.next { + var prevcontent string + if cur.prev != nil { + prevcontent = "(" + spew.Sprint(cur.prev.value) + "<-)" } else { - right = mid + prevcontent = "(nil)" } - } - if pq.comparator(v, data[left]) > 0 { - return left + 1 - } else { - return left + content += spew.Sprint(cur.value) + prevcontent + "-" } + if content[len(content)-1] == '-' { + content = content[:len(content)-1] + } + return content } func (pq *PriorityQueue) Push(v interface{}) { - defer func() { - if err := recover(); err != nil { + node := new(Node) + node.value = v - log.Println(pq.datas) - log.Println(pq.left, pq.right, pq.size) - log.Panic(err) + if pq.node == nil { + //创建索引 + index := new(Index) + index.nlen = 1 + index.node = node - } - }() + return + } + // find the node of index to start + idx := pq.index - if pq.size == 0 { + for { - pq.mid = len(pq.datas) / 2 - pq.left = pq.mid - 1 - pq.right = pq.mid + 1 - - pq.datas[pq.mid] = v - - log.Println(pq.datas) - log.Println(pq.left) - - } 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++ - - // } else { - - // if pq.left-1 < 0 { - // // 重建 datas - // pq.reMakeMemory() - // } - // pq.left-- - // pq.datas[pq.left] = v - // } - - idx := pq.search(v) - log.Println("idx:", idx) - if idx > pq.size/2 { - - if pq.right >= len(pq.datas) { - pq.reMakeMemory() - } - - offset := pq.left + 1 + idx - copy(pq.datas[offset+1:], pq.datas[offset:pq.right]) - pq.datas[offset] = v - pq.right++ - // log.Println("right: ", pq.datas) - - } else { - - if pq.left < 0 { - // 重建 datas - pq.reMakeMemory() - } - - offset := pq.left + 1 + idx - copy(pq.datas[pq.left:], pq.datas[pq.left+1:offset]) - pq.datas[offset] = v - pq.left-- - - // log.Println("left: ", pq.datas) + if idx.next == nil { + break } + if pq.comparator(v, idx.next.node.value) > 0 { + break + } + + idx = idx.next } + cur := idx.node + + //cur := pq.node + if pq.comparator(v, pq.node.value) > 0 { + pq.node = node + node.next = cur + + pq.index.node = pq.node + + // cur.prev = node + return + } + + for cur.next != nil { + + if pq.comparator(v, cur.next.value) > 0 { + temp := cur.next + cur.next = node + node.next = temp + // node.prev = cur + // temp.prev = node + + idx.nlen++ + + return + } + + cur = cur.next + } + + cur.next = node + + // node.prev = cur pq.size++ - log.Println("push:", pq.datas) - // if pq.isSorted { - // pq.isSorted = false - // } + } -// func (pq *PriorityQueue) PopTop() (interface{}, bool) { - -// return v, isok +// func (pq *PriorityQueue) Top() (interface{}, bool) { +// return pq.Get(0) // } -// func (pq *PriorityQueue) PopBottom() (interface{}, bool) { - -// return v, isok +// func (pq *PriorityQueue) Bottom() (interface{}, bool) { +// return pq.Get(pq.right - 1) // } -func (pq *PriorityQueue) Top() (interface{}, bool) { - return pq.Get(0) -} +// func (pq *PriorityQueue) Get(index int) (interface{}, bool) { +// if index < pq.size { +// return pq.Values()[index], true +// } +// return nil, false +// } -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.isSorted { - // utils.Sort(values, pq.comparator) - // pq.isSorted = true - // } - return pq.datas[pq.left:pq.right] -} +// func (pq *PriorityQueue) Values() []interface{} { +// // values := pq.datas[pq.left:pq.right] +// // if !pq.isSorted { +// // utils.Sort(values, pq.comparator) +// // pq.isSorted = true +// // } +// return pq.datas[pq.left:pq.right] +// } diff --git a/priority_queue/priority_queue_test.go b/priority_queue/priority_queue_test.go index be034a1..db4821c 100644 --- a/priority_queue/priority_queue_test.go +++ b/priority_queue/priority_queue_test.go @@ -1,10 +1,9 @@ package plist import ( + "log" "testing" - "github.com/davecgh/go-spew/spew" - "github.com/emirpasic/gods/utils" "github.com/Pallinder/go-randomdata" @@ -12,42 +11,37 @@ import ( "github.com/emirpasic/gods/trees/binaryheap" ) +type PriorityQ struct { + heap *binaryheap.Heap + comparator utils.Comparator + topk int + next *PriorityQ +} + +func (pq *PriorityQ) Push(v interface{}) { +} + +func TestNPQ(t *testing.T) { + h1 := binaryheap.NewWithIntComparator() + + for i := 0; i < 10; i++ { + h1.Push(i) + } + + h1.Values()[0] = 3 + + log.Println(h1) + +} + func TestPriorityQueue(t *testing.T) { p := NewWithInt() - for i := 0; i < 20; i++ { + for i := 0; i < 10; i++ { p.Push(randomdata.Number(0, 10000)) } - data := p.Values() - t.Error(data) - - content := "" - last := 0 - for i := 0; i < len(data); i++ { - if i == 0 { - content += "\n" - } else if i%5 == 0 { - content += spew.Sprintln(data[last:i]) - last = i - } - } - content += spew.Sprintln(data[last:]) - t.Error(content) - - lleft := p.search(0) - lmid := p.search(5000) - lright := p.search(10000) - - t.Error(lleft, lmid, lright) - t.Error(p.left+lleft, p.left+lmid, p.left+lright) - - t.Error(p.datas, p.size, len(p.Values())) - - for _, idx := range []int{5, 0, 21, 19} { - t.Error(p.Get(idx)) - } - + t.Error(p.String()) } func BenchmarkPriorityQueue(b *testing.B) {