diff --git a/priority_queue/debug.test b/priority_queue/debug.test new file mode 100755 index 0000000..8f2c6c3 Binary files /dev/null and b/priority_queue/debug.test differ diff --git a/priority_queue/priority_list.go b/priority_queue/priority_list.go new file mode 100644 index 0000000..00a0b1c --- /dev/null +++ b/priority_queue/priority_list.go @@ -0,0 +1,58 @@ +package plist + +import ( + "github.com/davecgh/go-spew/spew" +) + +// Node 节点结构 +type Node struct { + next *Node + value interface{} +} + +// PriorityList +type PriorityList struct { + size int + head *Node +} + +// New a node +func New() *PriorityList { + p := new(PriorityList) + return p +} + +// String 展示需要的 +func (pl *PriorityList) String() string { + + content := "" + + for cur := pl.head; cur != nil; cur = cur.next { + content += spew.Sprint(cur.value) + "-" + } + + if content != "" && content[len(content)-1] == '-' { + content = content[:len(content)-1] + } + + return content +} + +// insert 插入值 +func (pl *PriorityList) nodeInsert(cur *Node, value interface{}) { + if cur == nil { + temp := pl.head + pl.head = &Node{value: value} + pl.head.next = temp + return + } + + temp := cur.next + cur.next = &Node{value: value} + cur.next.next = temp +} + +// Size 长度 +func (pl *PriorityList) Size() int { + return pl.size +} diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go index fea7759..914c07b 100644 --- a/priority_queue/priority_queue.go +++ b/priority_queue/priority_queue.go @@ -1,190 +1,74 @@ package plist import ( - "github.com/davecgh/go-spew/spew" + "github.com/emirpasic/gods/trees/avltree" "github.com/emirpasic/gods/utils" ) // PriorityQueue 优先队列 适合数据量不大, 加索引 type PriorityQueue struct { - index *Index - indexlimit int - node *Node + avl *avltree.Tree size int comparator utils.Comparator + splitlimit int } -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.indexlimit = 10 - p.comparator = func(a, b interface{}) int { - if a.(int) > b.(int) { +func NewWithIntComparator() *PriorityQueue { + pq := new(PriorityQueue) + pq.comparator = func(v1, v2 interface{}) int { + if v1.(int) > v2.(int) { return 1 + } else if v1.(int) < v2.(int) { + return -1 } - return -1 + return 0 } - return p + pq.avl = avltree.NewWith(pq.comparator) + pq.size = 0 + return pq } -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 { - // prevcontent = "(nil)" - // } +func (pq *PriorityQueue) Push(value interface{}) { + var pl *PriorityList + pq.size++ - // content += spew.Sprint(cur.value) + prevcontent + "-" - content += spew.Sprint(cur.value) + "-" - } + floor, ok := pq.avl.Floor(value) + if ok { - if content != "" { - if content[len(content)-1] == '-' { - content = content[:len(content)-1] - } - } + pl = floor.Value.(*PriorityList) + cur := pl.head + pl.size++ - idxContent := "" - for idx := pq.index; idx != nil; idx = idx.next { - idxContent += spew.Sprint(idx.node.value) + "(" + spew.Sprint(idx.nlen) + ")-" - } + if pq.comparator(value, cur.value) > 0 { - return content + "\n" + idxContent -} - -func (pq *PriorityQueue) Push(v interface{}) { - - node := new(Node) - node.value = v - - if pq.node == nil { - //创建索引 - index := new(Index) - index.nlen = 1 - index.node = node - - pq.index = index - pq.node = node - - return - } - // find the node of index to start - idx := pq.index - - for { - - 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 - pq.index.nlen++ - - // cur.prev = node - return - } - - for i := 0; cur.next != nil; i++ { - - if i >= pq.indexlimit { - - if idx.next != nil && idx.next.nlen < pq.indexlimit { - idx.next.nlen += idx.nlen - pq.indexlimit - idx.nlen = pq.indexlimit - idx.next.node = cur - } else { - index := new(Index) - index.node = cur - index.nlen = idx.nlen - pq.indexlimit - index.next = idx.next - - idx.next = index - idx.nlen = pq.indexlimit - idx = index - i = 0 - } - - } - - 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++ - - // if pq.index.nlen >= pq.indexlimit { - // // 分裂 - - // } + temp := pl.head + pl.head = &Node{value: value} + pl.head.next = temp return } - cur = cur.next + for cur.next != nil { + if pq.comparator(value, cur.next.value) >= 0 { + temp := cur.next + cur.next = &Node{value: value} + cur.next.next = temp + return + } + cur = cur.next + } + // next == nil + cur.next = &Node{value: value} + return } - cur.next = node + pl = &PriorityList{} + pl.head = &Node{value: value} + pl.size++ - // node.prev = cur - pq.size++ - idx.nlen++ + pq.avl.Put(pl.head.value, pl) + + return } - -// 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.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 2a88264..228ecc4 100644 --- a/priority_queue/priority_queue_test.go +++ b/priority_queue/priority_queue_test.go @@ -1,9 +1,10 @@ package plist import ( - "log" "testing" + "github.com/emirpasic/gods/trees/avltree" + "github.com/emirpasic/gods/utils" "github.com/Pallinder/go-randomdata" @@ -11,53 +12,99 @@ 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() - +func TestPList(t *testing.T) { + pl := &PriorityList{} for i := 0; i < 10; i++ { - h1.Push(i) + pl.nodeInsert(nil, randomdata.Number(0, 10)) } + t.Error(pl.String()) - h1.Values()[0] = 3 - - log.Println(h1) + cur := pl.head + for i := 0; i < 5; i++ { + cur = cur.next + } + pl.nodeInsert(cur, 11) + t.Error(pl.String()) } -func TestPriorityQueue(t *testing.T) { - p := NewWithInt() +func TestPQ(t *testing.T) { - for i := 0; i < 100; i++ { - p.Push(randomdata.Number(0, 10000)) - t.Log(p.String()) + pq := NewWithIntComparator() + for i := 0; i < 1; i++ { + pq.Push(i) } - t.Error(p.String()) + iter := pq.avl.Iterator() + iter.Next() + pl := iter.Value().(*PriorityList) + t.Error(pq.size, pq.avl.Size(), pl.Size(), pl.head == nil, pl.head) } -func BenchmarkPriorityQueue(b *testing.B) { - p := NewWithInt() +func BenchmarkPQ(b *testing.B) { + pq := NewWithIntComparator() - // for i := 0; i < 10000; i++ { - // p.Push(randomdata.Number(0, 100000)) - // // p.Values() - // } + b.N = 1000000 + for i := b.N; i > 0; i-- { + pq.Push(i) + } + + iter := pq.avl.Iterator() + iter.Next() + + pl := iter.Value().(*PriorityList) + b.Log(pq.size, pq.avl.Size(), pl.Size(), pl.head) + b.Log(pl.head.value) + if pl.head.next != nil { + b.Log(pl.head.next.value) + } + + // b.Log("all:", pq.avl.Size(), pq.avl.Values()) +} + +func BenchmarkPList(b *testing.B) { - b.N = 100000 for i := 0; i < b.N; i++ { - p.Push(randomdata.Number(0, 100000)) + pl := &PriorityList{} + for i2 := 0; i2 < 5; i2++ { + cur := pl.head + for n := 0; n < i2; n++ { + cur = cur.next + } + pl.nodeInsert(cur, i2) + } + } +} + +func TestAvl(t *testing.T) { + + comparator := func(v1, v2 interface{}) int { + if v1.(int) > v2.(int) { + return 1 + } else if v1.(int) < v2.(int) { + return -1 + } + return 0 } + avl := avltree.NewWith(comparator) + for _, v := range []int{9, 2, 3, 4, 5, 6, 8, 1} { + avl.Put(v, v) + } + + iter := avl.Iterator() + iter.Next() + t.Error(avl.Values(), iter.Value()) + + f, ok := avl.Floor(10) + if ok { + t.Error("Floor", f) + } + + f, ok = avl.Ceiling(10) + if ok { + t.Error("Ceiling", f) + } } func TestHeap(t *testing.T) { @@ -73,35 +120,3 @@ func TestHeap(t *testing.T) { utils.Sort(heap.Values(), utils.IntComparator) } - -func BenchmarkList_InsertValues123(b *testing.B) { - a := func(v1, v2 interface{}) int { - if v1.(int) > v2.(int) { - return -1 - } - return 1 - } - - h := binaryheap.NewWith(a) - - TOPK := 50 - - for i := 0; i < TOPK*1000; i++ { - h.Push(i) - } - - b.StartTimer() - for i := 0; i < b.N; i++ { - h.Push(i) - l := []interface{}{} - for n := 0; n < TOPK; n++ { - v, _ := h.Pop() - l = append(l, v) - } - - for _, v := range l { - h.Push(v) - } - } - b.StopTimer() -}