diff --git a/priority_queue/avltree.go b/priority_queue/avltree.go index 8de9a82..0e16be4 100644 --- a/priority_queue/avltree.go +++ b/priority_queue/avltree.go @@ -11,6 +11,7 @@ package plist import ( "fmt" + "log" "github.com/emirpasic/gods/trees" "github.com/emirpasic/gods/utils" @@ -29,7 +30,7 @@ type Tree struct { // AvlNode is a single element within the tree type AvlNode struct { - Value interface{} + Value []interface{} Parent *AvlNode // Parent node Children [2]*AvlNode // Children nodes b int8 @@ -97,7 +98,11 @@ func (t *Tree) Values() []interface{} { values := make([]interface{}, t.size) it := t.Iterator() for i := 0; it.Next(); i++ { - values[i] = it.Value() + for _, v := range it.Value() { + log.Println(len(values), i) + values[i] = v + i++ + } } return values } @@ -128,7 +133,7 @@ func (t *Tree) Floor(value interface{}) (floor *AvlNode, found bool) { last := n for n != nil { - c := t.Comparator(value, n.Value) + c := t.Comparator(value, n.Value[0]) switch { case c == 0: return n, true @@ -159,7 +164,7 @@ func (t *Tree) Ceiling(key interface{}) (floor *AvlNode, found bool) { n := t.Root last := n for n != nil { - c := t.Comparator(key, n.Value) + c := t.Comparator(key, n.Value[0]) switch { case c == 0: return n, true @@ -200,14 +205,15 @@ func (t *Tree) put(key interface{}, p *AvlNode, qp **AvlNode) (bool, *AvlNode) { q := *qp if q == nil { t.size++ - *qp = &AvlNode{Value: key, Parent: p} + *qp = &AvlNode{Value: []interface{}{key}, Parent: p} return true, *qp } - c := t.Comparator(key, q.Value) + c := t.Comparator(key, q.Value[0]) if c == 0 { - q.Value = key - return false, q + t.size++ + q.Value = append(q.Value, key) + return false, q // TODO: } if c < 0 { @@ -232,7 +238,13 @@ func (t *Tree) remove(key interface{}, qp **AvlNode) bool { c := t.Comparator(key, q.Value) if c == 0 { + t.size-- + if len(q.Value) > 1 { + q.Value = q.Value[1:] + return false + } + if q.Children[1] == nil { if q.Children[0] != nil { q.Children[0].Parent = q.Parent @@ -240,7 +252,7 @@ func (t *Tree) remove(key interface{}, qp **AvlNode) bool { *qp = q.Children[0] return true } - fix := removeMin(&q.Children[1], &q.Value) + fix := removeMin(&q.Children[1], &q.Value[0]) if fix { return removeFix(-1, qp) } @@ -263,7 +275,7 @@ func (t *Tree) remove(key interface{}, qp **AvlNode) bool { func removeMin(qp **AvlNode, minKey *interface{}) bool { q := *qp if q.Children[0] == nil { - *minKey = q.Value + *minKey = q.Value[0] if q.Children[1] != nil { q.Children[1].Parent = q.Parent diff --git a/priority_queue/iterator.go b/priority_queue/iterator.go index 16bbb06..d383a02 100644 --- a/priority_queue/iterator.go +++ b/priority_queue/iterator.go @@ -64,7 +64,7 @@ func (iterator *Iterator) Prev() bool { // Value returns the current element's Value. // Does not modify the state of the iterator. -func (iterator *Iterator) Value() interface{} { +func (iterator *Iterator) Value() []interface{} { if iterator.node == nil { return nil } diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go index 84f45af..f9868ed 100644 --- a/priority_queue/priority_queue.go +++ b/priority_queue/priority_queue.go @@ -1,6 +1,8 @@ package plist import ( + "log" + "github.com/emirpasic/gods/utils" ) @@ -18,9 +20,15 @@ func NewWithInt() *PriorityQueue { p := new(PriorityQueue) p.comparator = func(a, b interface{}) int { + + if a.(int) == b.(int) { + return 0 + } + if a.(int) > b.(int) { return 1 } + return -1 } @@ -44,13 +52,32 @@ func (pq *PriorityQueue) Bottom() (interface{}, bool) { func (pq *PriorityQueue) Get(index int) (interface{}, bool) { var cur *AvlNode if index >= 0 { - cur := pq.Head + cur = pq.Head for index > 0 && cur != nil { index-- cur = cur.Prev() } } else { - cur := pq.Tail + cur = pq.Tail + for index < -1 && cur != nil { + index++ + cur = cur.Next() + } + } + return cur.Value, cur != nil +} + +// GetNode unsafe 破坏AvlNode属性会破坏整个数据结构 +func (pq *PriorityQueue) GetNode(index int) (*AvlNode, 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() @@ -80,10 +107,38 @@ func (pq *PriorityQueue) Push(v interface{}) { } } -func (pq *PriorityQueue) Remove(index int) interface{} { +func (pq *PriorityQueue) RemoveNode(node *AvlNode) { + if node == pq.Head { + pq.Head = node.Prev() + } + + if node == pq.Tail { + pq.Tail = node.Next() + } + + pq.data.remove(node.Value, &node) +} + +func (pq *PriorityQueue) Remove(index int) *AvlNode { + + node, ok := pq.GetNode(index) + if ok { + if node == pq.Head { + pq.Head = node.Prev() + } + + if node == pq.Tail { + pq.Tail = node.Next() + } + + next := node.Prev() + log.Println(next, next.Next()) + pq.data.remove(node.Value, &next) + return node + } return nil } -func (pq *PriorityQueue) Values(index int) []interface{} { +func (pq *PriorityQueue) Values() []interface{} { return pq.data.Values() } diff --git a/priority_queue/priority_queue_test.go b/priority_queue/priority_queue_test.go index d8778ac..5fcb7db 100644 --- a/priority_queue/priority_queue_test.go +++ b/priority_queue/priority_queue_test.go @@ -58,16 +58,21 @@ func TestPriorityQueuePush(t *testing.T) { } } -// func TestPustPriorityQueue(t *testing.T) { -// p := NewWithInt() +func TestPriorityQueueRemove(t *testing.T) { + p := NewWithInt() -// for i := 0; i < 100; i++ { -// p.Push(randomdata.Number(0, 10000)) -// t.Log(p.String()) -// } + for i := 0; i < 20; i++ { + p.Push(randomdata.Number(0, 10)) + } + t.Error(p.Values()) + n, ok := p.GetNode(0) + t.Error(n, ok, p.Head, p.Tail) -// t.Error(p.String()) -// } + for i := 0; i < 20; i++ { + t.Error(p.Remove(0), p.data.Size()) + t.Error(p.Values()) + } +} func BenchmarkPriorityQueuePush(b *testing.B) { p := NewWithInt() @@ -78,6 +83,23 @@ func BenchmarkPriorityQueuePush(b *testing.B) { } } +func BenchmarkPriorityQueueRemove(b *testing.B) { + p := NewWithInt() + + for i := 0; i < 1000000; i++ { + p.Push(randomdata.Number(0, 100000)) + } + + b.StartTimer() + b.N = 1000000 + for i := 0; i < b.N-100; i++ { + p.Remove(randomdata.Number(0, 100)) + } + for p.Remove(0) != nil { + + } +} + func BenchmarkPriorityQueueGet(b *testing.B) { p := NewWithInt() @@ -98,14 +120,12 @@ func BenchmarkPriorityQueueGet(b *testing.B) { func TestAVL(t *testing.T) { avl := NewWithIntComparator() - for i := 0; i < 100000; i++ { + for i := 0; i < 100; i++ { v := randomdata.Number(0, 100) - n := avl.Put(v) - if v != n.Value.(int) { - t.Error(v, n) - } - + avl.Put(v) } + + t.Error(avl.size) t.Error(avl.Values()) f, ok := avl.Ceiling(1000) t.Error(f, ok) @@ -121,13 +141,11 @@ func TestAVL(t *testing.T) { 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() } }