diff --git a/priority_queue/avltree.go b/priority_queue/avltree.go index db9a559..8de9a82 100644 --- a/priority_queue/avltree.go +++ b/priority_queue/avltree.go @@ -23,13 +23,12 @@ func assertTreeImplementation() { // Tree holds elements of the AVL tree. type Tree struct { Root *AvlNode // Root node - Comparator utils.Comparator // Key comparator + Comparator utils.Comparator // Value comparator size int // Total number of keys in the tree } // AvlNode is a single element within the tree type AvlNode struct { - Key interface{} Value interface{} Parent *AvlNode // Parent node Children [2]*AvlNode // Children nodes @@ -52,33 +51,33 @@ func NewWithStringComparator() *Tree { } // Put inserts node into the tree. -// Key should adhere to the comparator's type assertion, otherwise method panics. -func (t *Tree) Put(key interface{}, value interface{}) (putNode *AvlNode) { - _, putNode = t.put(key, value, nil, &t.Root) +// Value should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Put(key interface{}) (putNode *AvlNode) { + _, putNode = t.put(key, nil, &t.Root) return } -// Get searches the node in the tree by key and returns its value or nil if key is not found in tree. +// Find searches the node in the tree by key and returns its value or nil if key is not found in tree. // Second return parameter is true if key was found, otherwise false. -// Key should adhere to the comparator's type assertion, otherwise method panics. -func (t *Tree) Get(key interface{}) (value interface{}, found bool) { +// Value should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Find(key interface{}) (node *AvlNode, found bool) { n := t.Root for n != nil { - cmp := t.Comparator(key, n.Key) + cmp := t.Comparator(key, n.Value) switch { case cmp == 0: - return n.Value, true + return n, true case cmp < 0: n = n.Children[0] case cmp > 0: n = n.Children[1] } } - return nil, false + return n, false } // Remove remove the node from the tree by key. -// Key should adhere to the comparator's type assertion, otherwise method panics. +// Value should adhere to the comparator's type assertion, otherwise method panics. func (t *Tree) Remove(key interface{}) { t.remove(key, &t.Root) } @@ -93,16 +92,6 @@ func (t *Tree) Size() int { return t.size } -// Keys returns all keys in-order -func (t *Tree) Keys() []interface{} { - keys := make([]interface{}, t.size) - it := t.Iterator() - for i := 0; it.Next(); i++ { - keys[i] = it.Key() - } - return keys -} - // Values returns all values in-order based on the key. func (t *Tree) Values() []interface{} { values := make([]interface{}, t.size) @@ -132,14 +121,14 @@ func (t *Tree) Right() *AvlNode { // A floor node may not be found, either because the tree is empty, or because // all nodes in the tree is larger than the given node. // -// Key should adhere to the comparator's type assertion, otherwise method panics. -func (t *Tree) Floor(key interface{}) (floor *AvlNode, found bool) { +// Value should adhere to the comparator's type assertion, otherwise method panics. +func (t *Tree) Floor(value interface{}) (floor *AvlNode, found bool) { found = false n := t.Root last := n for n != nil { - c := t.Comparator(key, n.Key) + c := t.Comparator(value, n.Value) switch { case c == 0: return n, true @@ -164,13 +153,13 @@ func (t *Tree) Floor(key interface{}) (floor *AvlNode, found bool) { // A ceiling node may not be found, either because the tree is empty, or because // all nodes in the tree is smaller than the given node. // -// Key should adhere to the comparator's type assertion, otherwise method panics. +// Value should adhere to the comparator's type assertion, otherwise method panics. func (t *Tree) Ceiling(key interface{}) (floor *AvlNode, found bool) { found = false n := t.Root last := n for n != nil { - c := t.Comparator(key, n.Key) + c := t.Comparator(key, n.Value) switch { case c == 0: return n, true @@ -204,21 +193,20 @@ func (t *Tree) String() string { } func (n *AvlNode) String() string { - return fmt.Sprintf("%v", n.Key) + return fmt.Sprintf("%v", n.Value) } -func (t *Tree) put(key interface{}, value interface{}, p *AvlNode, qp **AvlNode) (bool, *AvlNode) { +func (t *Tree) put(key interface{}, p *AvlNode, qp **AvlNode) (bool, *AvlNode) { q := *qp if q == nil { t.size++ - *qp = &AvlNode{Key: key, Value: value, Parent: p} + *qp = &AvlNode{Value: key, Parent: p} return true, *qp } - c := t.Comparator(key, q.Key) + c := t.Comparator(key, q.Value) if c == 0 { - q.Key = key - q.Value = value + q.Value = key return false, q } @@ -229,7 +217,7 @@ func (t *Tree) put(key interface{}, value interface{}, p *AvlNode, qp **AvlNode) } a := (c + 1) / 2 var fix bool - fix, node := t.put(key, value, q, &q.Children[a]) + fix, node := t.put(key, q, &q.Children[a]) if fix { return putFix(int8(c), qp), node } @@ -242,7 +230,7 @@ func (t *Tree) remove(key interface{}, qp **AvlNode) bool { return false } - c := t.Comparator(key, q.Key) + c := t.Comparator(key, q.Value) if c == 0 { t.size-- if q.Children[1] == nil { @@ -252,7 +240,7 @@ func (t *Tree) remove(key interface{}, qp **AvlNode) bool { *qp = q.Children[0] return true } - fix := removeMin(&q.Children[1], &q.Key, &q.Value) + fix := removeMin(&q.Children[1], &q.Value) if fix { return removeFix(-1, qp) } @@ -272,18 +260,18 @@ func (t *Tree) remove(key interface{}, qp **AvlNode) bool { return false } -func removeMin(qp **AvlNode, minKey *interface{}, minVal *interface{}) bool { +func removeMin(qp **AvlNode, minKey *interface{}) bool { q := *qp if q.Children[0] == nil { - *minKey = q.Key - *minVal = q.Value + *minKey = q.Value + if q.Children[1] != nil { q.Children[1].Parent = q.Parent } *qp = q.Children[1] return true } - fix := removeMin(&q.Children[0], minKey, minVal) + fix := removeMin(&q.Children[0], minKey) if fix { return removeFix(1, qp) } diff --git a/priority_queue/iterator.go b/priority_queue/iterator.go index 42570c5..16bbb06 100644 --- a/priority_queue/iterator.go +++ b/priority_queue/iterator.go @@ -4,12 +4,6 @@ package plist -import "github.com/emirpasic/gods/containers" - -func assertIteratorImplementation() { - var _ containers.ReverseIteratorWithKey = (*Iterator)(nil) -} - // Iterator holding the iterator's state type Iterator struct { tree *Tree @@ -24,7 +18,7 @@ const ( ) // Iterator returns a stateful iterator whose elements are key/value pairs. -func (tree *Tree) Iterator() containers.ReverseIteratorWithKey { +func (tree *Tree) Iterator() *Iterator { return &Iterator{tree: tree, node: nil, position: begin} } @@ -68,7 +62,7 @@ func (iterator *Iterator) Prev() bool { return true } -// Value returns the current element's value. +// Value returns the current element's Value. // Does not modify the state of the iterator. func (iterator *Iterator) Value() interface{} { if iterator.node == nil { @@ -77,15 +71,6 @@ func (iterator *Iterator) Value() interface{} { return iterator.node.Value } -// Key returns the current element's key. -// Does not modify the state of the iterator. -func (iterator *Iterator) Key() interface{} { - if iterator.node == nil { - return nil - } - return iterator.node.Key -} - // Begin resets the iterator to its initial state (one-before-first) // Call Next() to fetch the first element if any. func (iterator *Iterator) Begin() { diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go index af6fba0..84f45af 100644 --- a/priority_queue/priority_queue.go +++ b/priority_queue/priority_queue.go @@ -1,27 +1,18 @@ 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 *avltree.Tree - indexlimit int + data *Tree - node *Node - size int + Head *AvlNode + Tail *AvlNode comparator utils.Comparator } -type Node struct { - value interface{} - // prev *Node - next *Node -} - // NewWithInt compare use int func NewWithInt() *PriorityQueue { p := new(PriorityQueue) @@ -33,136 +24,66 @@ func NewWithInt() *PriorityQueue { return -1 } - p.indexlimit = 10 - p.index = avltree.NewWith(p.comparator) + p.data = NewWith(p.comparator) return p } func (pq *PriorityQueue) String() string { - content := "" - for cur := pq.node; cur != nil; cur = cur.next { - content += spew.Sprint(cur.value) + "-" - } - - if content != "" { - if content[len(content)-1] == '-' { - content = content[:len(content)-1] - } - } - return content + return pq.data.String() } -// func (pq *PriorityQueue) Get(index int) (interface{}, bool) { -// if index < 0 || index >= pq.size { -// return nil, false -// } +func (pq *PriorityQueue) Top() (interface{}, bool) { + return pq.Head, pq.Head != nil +} -// idx := pq.index -// movesize := index -// for { -// if movesize-idx.nlen <= 0 { -// break -// } else { -// movesize -= idx.nlen -// idx = idx.next -// } -// } +func (pq *PriorityQueue) Bottom() (interface{}, bool) { + return pq.Tail, pq.Tail != nil +} -// cur := idx.node -// for movesize > 0 { -// movesize-- -// cur = cur.next -// } +func (pq *PriorityQueue) Get(index int) (interface{}, bool) { + var cur *AvlNode + if index >= 0 { + cur := pq.Head + for index > 0 && cur != nil { + index-- + cur = cur.Prev() + } + } else { + cur := pq.Tail + for index < -1 && cur != nil { + index++ + cur = cur.Next() + } + } -// return cur.value, true -// } + return cur, cur != nil +} -// func (pq *PriorityQueue) Push(v interface{}) { +func (pq *PriorityQueue) Push(v interface{}) { -// node := &Node{value: v} -// pq.size++ + pnode := pq.data.Put(v) + if pq.Head == nil { + pq.Head = pnode + pq.Tail = pnode + return + } -// if pq.node == nil { -// //创建索引 -// pq.index.Put(node, 1) + if pq.comparator(v, pq.Head.Value) > 0 { + pq.Head = pnode + return + } -// pq.node = node -// return -// } -// // find the node of index to start -// fool, ok := pq.index.Ceiling(v) -// cur := idx.node + if pq.comparator(v, pq.Tail.Value) < 0 { + pq.Tail = pnode + return + } +} -// if pq.comparator(v, pq.node.value) > 0 { -// pq.node = node -// node.next = cur +func (pq *PriorityQueue) Remove(index int) interface{} { + return nil +} -// pq.index.node = pq.node -// pq.index.nlen++ -// 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 -// idx = idx.next -// } 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 -// idx.nlen++ -// return -// } -// cur = cur.next - -// } - -// cur.next = node -// idx.nlen++ - -// } - -// 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] -// } +func (pq *PriorityQueue) Values(index int) []interface{} { + return pq.data.Values() +} diff --git a/priority_queue/priority_queue_test.go b/priority_queue/priority_queue_test.go index 2d8ea31..d8778ac 100644 --- a/priority_queue/priority_queue_test.go +++ b/priority_queue/priority_queue_test.go @@ -10,28 +10,53 @@ import ( "github.com/emirpasic/gods/trees/binaryheap" ) -// func TestGetPriorityQueue(t *testing.T) { -// p := NewWithInt() +func TestPriorityQueueGet(t *testing.T) { + p := NewWithInt() -// var l []int -// for i := 0; i < 10; i++ { -// l = append(l, randomdata.Number(0, 10000)) -// } + var l []int + for i := 0; i < 10; i++ { + l = append(l, randomdata.Number(0, 1000)) + } -// for _, v := range l { -// p.Push(v) -// t.Log(p.String()) -// } + for _, v := range l { + p.Push(v) + t.Log(p.String()) + } -// t.Error(l) -// t.Error(p.String()) + t.Error(p.data.Values()) -// for _, i := range []int{-1, 0, p.size / 2, p.size - 1, p.size} { -// v, ok := p.Get(i) -// t.Error(i, v, ok) -// } +} -// } +func TestPriorityQueuePush(t *testing.T) { + p := NewWithInt() + + var l []int + for i := 0; i < 20; i++ { + l = append(l, randomdata.Number(0, 5)) + } + + for _, v := range l { + p.Push(v) + t.Log(p.String()) + } + + t.Error(l) + t.Error(p.data.Values(), p.Head, p.Tail) + + cur := p.Head + for cur != nil { + t.Error(cur.Value) + cur = cur.Prev() + } + + t.Error("-----") + + cur = p.Tail + for cur != nil { + t.Error(cur.Value) + cur = cur.Next() + } +} // func TestPustPriorityQueue(t *testing.T) { // p := NewWithInt() @@ -44,43 +69,38 @@ import ( // t.Error(p.String()) // } -// func BenchmarkPriorityQueuePush(b *testing.B) { -// p := NewWithInt() +func BenchmarkPriorityQueuePush(b *testing.B) { + p := NewWithInt() -// // for i := 0; i < 10000; i++ { -// // p.Push(randomdata.Number(0, 100000)) -// // // p.Values() -// // } + b.N = 1000000 + for i := 0; i < b.N; i++ { + p.Push(randomdata.Number(0, 100000)) + } +} -// b.N = 10000 -// for i := 0; i < b.N; i++ { -// p.Push(randomdata.Number(0, 100000)) -// } +func BenchmarkPriorityQueueGet(b *testing.B) { + p := NewWithInt() -// } + for i := 0; i < 500000; i++ { + p.Push(randomdata.Number(0, 100000)) + // p.Values() + } -// func BenchmarkPriorityQueueGet(b *testing.B) { -// p := NewWithInt() + b.ResetTimer() + b.StartTimer() + b.N = 100000 + for i := 0; i < b.N; i++ { + p.Get(randomdata.Number(0, 1000)) + } + b.StopTimer() -// for i := 0; i < 10000; i++ { -// p.Push(randomdata.Number(0, 100000)) -// // p.Values() -// } - -// b.StartTimer() -// b.N = 100000 -// for i := 0; i < b.N; i++ { -// p.Get(randomdata.Number(0, 10000)) -// } -// b.StopTimer() - -// } +} func TestAVL(t *testing.T) { avl := NewWithIntComparator() for i := 0; i < 100000; i++ { v := randomdata.Number(0, 100) - n := avl.Put(v, v) + n := avl.Put(v) if v != n.Value.(int) { t.Error(v, n) } @@ -98,6 +118,18 @@ func TestAVL(t *testing.T) { if ok { t.Error(f.Next().Value) } + + root := avl.Root + for root != nil { + t.Error(root.Value) + root = root.Next() + } + + root = avl.Root + for root != nil { + t.Error(root.Value) + root = root.Prev() + } } func BenchmarkAVL(b *testing.B) { @@ -107,11 +139,11 @@ func BenchmarkAVL(b *testing.B) { b.StartTimer() for i := 0; i < b.N; i++ { v := randomdata.Number(0, 100000000) - avl.Put(v, v) + avl.Put(v) } for i := 0; i < b.N; i++ { - avl.Get(i) + avl.Find(i) } b.StopTimer()