From 0fb5a2ca4a48d2a65e179adb330682b9ea5d30ca Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Mon, 25 Feb 2019 02:37:34 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8D=95=E7=9A=84=E4=BC=98=E5=85=88?= =?UTF-8?q?=E9=93=BE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- circular_linked/circular_linked.go | 249 --------------------- circular_linked/circular_linked_test.go | 65 ------ priority_list/iterator.go | 70 ++++++ priority_list/plist_node.go | 18 -- priority_list/priority_list.go | 278 ++++++++---------------- priority_list/priority_list_test.go | 99 +++------ 6 files changed, 183 insertions(+), 596 deletions(-) delete mode 100644 circular_linked/circular_linked.go delete mode 100644 circular_linked/circular_linked_test.go create mode 100644 priority_list/iterator.go delete mode 100644 priority_list/plist_node.go diff --git a/circular_linked/circular_linked.go b/circular_linked/circular_linked.go deleted file mode 100644 index a80eb55..0000000 --- a/circular_linked/circular_linked.go +++ /dev/null @@ -1,249 +0,0 @@ -package clinked - -import ( - "log" - "strings" - - "github.com/davecgh/go-spew/spew" -) - -// CNode 循环链表 三色标记 不确定是否会清除循环引用, 网上说会 -type CNode struct { - value interface{} - prev *CNode - next *CNode -} - -// GetValue 获取到Node的值 -func (node *CNode) GetValue() interface{} { - return node.value -} - -// SetValue 获取到Node的值 -func (node *CNode) SetValue(value interface{}) { - node.value = value -} - -// CircularLinked 循环链表 -type CircularLinked struct { - cursor *CNode - head *CNode - tail *CNode - size uint64 -} - -// NewCircularLinked create a CircularLinked -func NewCircularLinked(values ...interface{}) *CircularLinked { - list := &CircularLinked{} - if len(values) > 0 { - list.Append(values...) - } - return list -} - -// Head 链表的首 -func (list *CircularLinked) Head() *CNode { - return list.head -} - -// Tail 链表的首 -func (list *CircularLinked) Tail() *CNode { - return list.tail -} - -// Cursor get current Cursor -func (list *CircularLinked) Cursor() *CNode { - if list.cursor == nil { - list.cursor = list.head - } - return list.cursor -} - -// MoveNext get next Cursor -func (list *CircularLinked) MoveNext() *CNode { - if list.cursor == nil { - list.cursor = list.head - } - list.cursor = list.cursor.next - return list.cursor -} - -// MovePrev get prev Cursor -func (list *CircularLinked) MovePrev() *CNode { - if list.cursor == nil { - list.cursor = list.head - } - list.cursor = list.cursor.prev - return list.cursor -} - -// CursorToHead cursor move to head -func (list *CircularLinked) CursorToHead() *CNode { - list.cursor = list.head - return list.cursor -} - -// CursorToTail cursor move to tail -func (list *CircularLinked) CursorToTail() *CNode { - list.cursor = list.tail - return list.cursor -} - -// GetLoopValues 获取从头到尾的值 -func (list *CircularLinked) GetLoopValues() []*CNode { - var result []*CNode - - if list.head != nil { - result = append(result, list.head) - for cur := list.head.next; cur != list.head; cur = cur.next { - result = append(result, cur) - } - } - return result -} - -// Append a value (one or more) at the end of the list (same as Append()) -func (list *CircularLinked) Append(values ...interface{}) { - for _, value := range values { - node := &CNode{value: value} - if list.size == 0 { - list.head = node - list.tail = node - node.next = node - node.prev = node - } else { - list.tail.next = node - node.next = list.head - node.prev = list.tail - list.tail = node - } - list.size++ - } -} - -// Remove 移除一些节点 -func (list *CircularLinked) Remove(node *CNode) { - - switch list.size { - case 0: - list.errorNotInList(node) - case 1: - if list.head == node { - list.head = nil - list.tail = nil - node.next = nil - node.prev = nil - list.cursor = nil - list.size-- - } else { - list.errorNotInList(node) - } - case 2: - - node.prev = nil - node.next = nil - - switch node { - case list.head: - list.head = list.tail - list.tail.prev = list.head - list.head.next = list.tail - list.cursor = list.head - list.size-- - case list.tail: - list.tail = list.head - list.tail.prev = list.head - list.head.next = list.tail - list.cursor = list.head - list.size-- - default: - list.errorNotInList(node) - } - - default: - switch node { - case list.head: - _, next := list.cutAndSplice(node) - list.size-- - list.head = next - if list.cursor == node { - list.cursor = next - } - case list.tail: - prev, _ := list.cutAndSplice(node) - list.size-- - list.tail = prev - if list.cursor == node { - list.cursor = prev - } - default: - _, next := list.cutAndSplice(node) - list.size-- - if list.cursor == node { - list.cursor = next - } - } - } - -} - -// LookCursor for list show -func (list *CircularLinked) LookCursor() string { - cursor := list.Cursor() - - content := "->[" - cur := list.head - if list.size != 0 { - for size := uint64(0); size < list.size; size++ { - if cursor == cur { - content += "(" + spew.Sprint(cur.value) + ")" + ", " - } else { - content += spew.Sprint(cur.value) + ", " - } - - cur = cur.next - } - } - content = strings.TrimRight(content, ", ") - showlen := len(content) - if showlen >= 64 { - showlen = 64 - } - content += "]" + content[0:showlen] + " ..." - return content -} - -// Clear for list show -func (list *CircularLinked) Clear() { - if list.size != 0 { - list.head.prev = nil - list.tail.next = nil - list.head = nil - list.tail = nil - list.cursor = nil - list.size = 0 - } -} - -// Size for list show -func (list *CircularLinked) Size() uint64 { - return list.size -} - -func (list *CircularLinked) errorNotInList(node *CNode) { - log.Println("the node value ", spew.Sprint(node), " is not in list") -} - -// cutAndSplice (不考虑边界情况) -func (list *CircularLinked) cutAndSplice(node *CNode) (prev, next *CNode) { - prev = node.prev - next = node.next - - prev.next = next - next.prev = prev - - node.prev = nil - node.next = nil - - return prev, next -} diff --git a/circular_linked/circular_linked_test.go b/circular_linked/circular_linked_test.go deleted file mode 100644 index 467e22e..0000000 --- a/circular_linked/circular_linked_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package clinked - -import "testing" - -func TestCircularLinkedLookUp(t *testing.T) { - - cl := NewCircularLinked(1, 2, 3, 4, 5, 6) - if !(cl.head.value.(int) == 1 && cl.tail.value.(int) == 6) { - t.Error(cl.LookCursor()) - } - - cl = NewCircularLinked(6, 2, 3, 4, 5, 1) - if !(cl.head.value.(int) == 6 && cl.tail.value.(int) == 1) { - t.Error("New List is error:", cl.LookCursor()) - } - - if cl.MoveNext().value.(int) != 2 { - t.Error("CursorNext error:", cl.LookCursor()) - } - - cl = NewCircularLinked(0, 1, 2, 3, 4, 5) - for i := 0; i < 6; i++ { - if cl.Cursor().value.(int) != i { - t.Error("CursorNext error:", cl.LookCursor()) - } - cl.MoveNext() - } - - for i := 0; i < 6; i++ { - if cl.Cursor().value.(int) != i { - t.Error("CursorNext loop error:", cl.LookCursor()) - } - cl.MoveNext() - } - - cl = NewCircularLinked(6, 2, 3, 4, 5, 1) - cl.Remove(cl.Cursor()) - if cl.Cursor().value != 2 { - t.Error("Remove Head is error", cl.LookCursor()) - } - cl.Remove(cl.CursorToTail()) - if cl.Cursor().value != 5 { - t.Error("Remove CursorToTail is error", cl.LookCursor()) - } - - cl.Remove(cl.CursorToHead()) - if cl.Cursor().value != 3 { - t.Error("Remove CursorToHead is error", cl.LookCursor()) - } - - limitCount := 0 - for cl.Size() > 0 { - cl.Remove(cl.Cursor()) - limitCount++ - if limitCount >= 10 { - t.Error("Not Clear", cl.LookCursor()) - break - } - } - - cl.Remove(cl.CursorToHead()) // nil is not in list is success! - if cl.head != nil || cl.tail != nil || cl.cursor != nil { - t.Error("Remove Boundary error") - } -} diff --git a/priority_list/iterator.go b/priority_list/iterator.go new file mode 100644 index 0000000..651a048 --- /dev/null +++ b/priority_list/iterator.go @@ -0,0 +1,70 @@ +package plist + +type Iterator struct { + pl *PriorityList + cur *Node +} + +func (iter *Iterator) Value() interface{} { + return iter.cur.Value +} + +func (iter *Iterator) RingNext() bool { + if iter.pl.size == 0 { + return false + } + + iter.cur = iter.cur.next + if iter.cur == iter.pl.tail { + iter.cur = iter.pl.head.next + } + + return true +} + +func (iter *Iterator) Next() bool { + if iter.cur == iter.pl.tail { + return false + } + if iter.cur.next == iter.pl.tail { + iter.cur = iter.cur.next + return false + } + iter.cur = iter.cur.next + return true +} + +func (iter *Iterator) RingPrev() bool { + if iter.pl.size == 0 { + return false + } + + iter.cur = iter.cur.prev + if iter.cur == iter.pl.head { + iter.cur = iter.pl.tail.prev + } + + return true +} + +func (iter *Iterator) Prev() bool { + + if iter.cur == iter.pl.head { + return false + } + if iter.cur.prev == iter.pl.head { + iter.cur = iter.cur.prev + return false + } + + iter.cur = iter.cur.prev + return true +} + +func (iter *Iterator) MoveHead() { + iter.cur = iter.pl.head +} + +func (iter *Iterator) MoveTail() { + iter.cur = iter.pl.tail +} diff --git a/priority_list/plist_node.go b/priority_list/plist_node.go deleted file mode 100644 index eee306a..0000000 --- a/priority_list/plist_node.go +++ /dev/null @@ -1,18 +0,0 @@ -package plist - -// NodeInt plist 现成的Int节点, 可以作为例子 -type NodeInt struct { - Node -} - -// Compare plist 现成的Int节点Compare覆盖 -func (fl *NodeInt) Compare(v INode) bool { - return fl.GetValue().(int) > v.GetValue().(int) -} - -// NewNodeInt plist 现成的Int节点, New一个NodeInt -func NewNodeInt(v int) (fl *NodeInt) { - fl = new(NodeInt) - fl.SetValue(v) - return fl -} diff --git a/priority_list/priority_list.go b/priority_list/priority_list.go index 547c217..c64765a 100644 --- a/priority_list/priority_list.go +++ b/priority_list/priority_list.go @@ -2,6 +2,7 @@ package plist import ( "github.com/davecgh/go-spew/spew" + "github.com/emirpasic/gods/utils" ) // INode 比较的必须继承的接口 @@ -21,59 +22,18 @@ type INode interface { // Node 优先链表的节点 type Node struct { - INode - prev, next INode + next, prev *Node // isrelease bool - value interface{} -} - -// NewNode 创建一个PriorityList 节点 -func NewNode(v interface{}) *Node { - n := new(Node) - n.SetValue(v) - return n -} - -// GetValue 获取值 -func (node *Node) GetValue() interface{} { - return node.value -} - -// SetValue 设置值 -func (node *Node) SetValue(v interface{}) { - node.value = v -} - -// GetPrev 获取left值 -func (node *Node) GetPrev() INode { - return node.prev -} - -// SetPrev 设置left值 -func (node *Node) SetPrev(n INode) { - node.prev = n -} - -// GetNext 设置right值 -func (node *Node) GetNext() INode { - return node.next -} - -// SetNext 获取left值 -func (node *Node) SetNext(n INode) { - node.next = n -} - -func (node *Node) String() string { - return spew.Sprint(node.value) + Value interface{} } // PriorityList 优先列表 type PriorityList struct { - head INode - tail INode + head *Node + tail *Node - size int + compartor utils.Comparator + size int } // Size 长度 @@ -84,135 +44,73 @@ func (pl *PriorityList) Size() int { // Clear 清空链表, 如果外部有引用其中一个节点 要把节点Prev Next值为nil, 三色标记 func (pl *PriorityList) Clear() { pl.head = nil - pl.tail = nil pl.size = 0 } -// GetCompare 获取比较的节点 compare >= 11这个节点小的值 [15,12,9,8,6,1] = 9 -func (pl *PriorityList) GetCompare(cNode INode) INode { - cur := pl.head - for cur != nil { - if !cur.Compare(cNode) { - return cur - } - cur = cur.GetNext() - } - return nil -} - -// GetCompareReverse 逆序获取比较的节点 compare >= 11这个节点大的值 [15,12,9,8,6,1] = 12 -func (pl *PriorityList) GetCompareReverse(cNode INode) INode { - cur := pl.tail - for cur != nil { - if cur.Compare(cNode) { - return cur - } - cur = cur.GetPrev() - } - return nil -} - -// ForEach 顺序遍历 -func (pl *PriorityList) ForEach(eachfunc func(INode) bool) { - cur := pl.head - for cur != nil { - if !eachfunc(cur) { - break - } - cur = cur.GetNext() - } -} - -// ForEachReverse 逆遍历 -func (pl *PriorityList) ForEachReverse(eachfunc func(INode) bool) { - cur := pl.tail - for cur != nil { - if !eachfunc(cur) { - break - } - cur = cur.GetPrev() - } -} +// // ForEach 顺序遍历 +// func (pl *PriorityList) ForEach(eachfunc func(*Node) *Node) { +// cur := pl.head +// } // Get 获取索引长度 -func (pl *PriorityList) Get(idx int) INode { - if idx >= pl.size { - return nil +func (pl *PriorityList) Get(idx int) interface{} { + node := pl.GetNode(idx) + if node != nil { + return node.Value } - cur := pl.head - for i := 0; i < idx; i++ { - cur = cur.GetNext() - } - return cur + return nil } -// GetReverse 腻序获取索引长度 -func (pl *PriorityList) GetReverse(idx int) INode { - if idx >= pl.size { - return nil - } - cur := pl.tail - for i := 0; i < idx; i++ { - cur = cur.GetPrev() - } - return cur -} - -// Remove 删除节点 -func (pl *PriorityList) Remove(node INode) { - - if pl.size <= 1 { - pl.head = nil - pl.tail = nil - if pl.size == 0 { - panic("the node is not in this list, node:" + spew.Sprint(node)) +// GetNode 获取索引长度 +func (pl *PriorityList) GetNode(idx int) *Node { + if idx >= 0 { + cur := pl.head.next + for i := 0; cur != pl.tail; i++ { + if i == idx { + return cur + } + cur = cur.next } - pl.size = 0 + } else { + cur := pl.tail.prev + for i := -1; cur != pl.head; i-- { + if i == idx { + return cur + } + cur = cur.prev + } + } + + return nil +} + +// Remove 删除节点 +func (pl *PriorityList) Remove(idx int) { + pl.RemoveNode(pl.GetNode(idx)) +} + +// RemoveNode 删除节点 +func (pl *PriorityList) RemoveNode(node *Node) { + if node == nil { return } + prev := node.prev + next := node.next + + prev.next = next + next.prev = prev + pl.size-- - prev := node.GetPrev() - next := node.GetNext() - - if prev == nil { - pl.head = next - next.SetPrev(nil) - node.SetNext(nil) - } else if next == nil { - pl.tail = prev - prev.SetNext(nil) - node.SetPrev(nil) - } else { - prev.SetNext(next) - next.SetPrev(prev) - - node.SetPrev(nil) - node.SetNext(nil) - } -} - -// RemoveIndex 删除节点 并获取该节点 -func (pl *PriorityList) RemoveIndex(idx int) INode { - result := pl.Get(idx) - pl.Remove(result) - return result -} - -// RemoveReverseIndex 逆顺序删除节点 并获取该节点 -func (pl *PriorityList) RemoveReverseIndex(idx int) INode { - result := pl.GetReverse(idx) - pl.Remove(result) - return result } func (pl *PriorityList) String() string { content := "[" - cur := pl.head - for cur != nil { - content += spew.Sprint(cur.GetValue()) + "," - cur = cur.GetNext() + cur := pl.head.next + for cur != pl.tail { + content += spew.Sprint(cur.Value) + "," + cur = cur.next } if content[len(content)-1:] == "," { @@ -223,48 +121,44 @@ func (pl *PriorityList) String() string { return content } +func (pl *PriorityList) Iterator() *Iterator { + return &Iterator{pl: pl, cur: pl.head} +} + // Insert 插入节点 -func (pl *PriorityList) Insert(node INode) { +func (pl *PriorityList) Insert(value interface{}) { pl.size++ - if pl.head == nil { - pl.head = node - pl.tail = node - return - } - - cur := pl.head - for { - if !cur.Compare(node) { - // 插入该值 - prev := cur.GetPrev() - if prev == nil { - pl.head.SetPrev(node) - node.SetNext(pl.head) - pl.head = node - } else { - prev.SetNext(node) - node.SetNext(cur) - cur.SetPrev(node) - node.SetPrev(prev) - } + inode := &Node{Value: value} + cur := pl.head.next + for i := 0; cur != pl.tail; i++ { + if pl.compartor(value, cur.Value) > 0 { + prev := cur.prev + prev.next = inode + cur.prev = inode + inode.prev = prev + inode.next = cur return } - - next := cur.GetNext() - if next == nil { - cur.SetNext(node) - node.SetPrev(cur) - pl.tail = node - return - } - cur = next - + cur = cur.next } + prev := cur.prev + prev.next = inode + cur.prev = inode + inode.prev = prev + inode.next = cur } // New 创建 PriorityList -func New() *PriorityList { - return new(PriorityList) +func New(compartor utils.Comparator) *PriorityList { + pl := new(PriorityList) + pl.compartor = compartor + pl.head = new(Node) + pl.tail = new(Node) + + pl.head.next = pl.tail + pl.tail.prev = pl.head + + return pl } diff --git a/priority_list/priority_list_test.go b/priority_list/priority_list_test.go index 4ccad2c..fd167b5 100644 --- a/priority_list/priority_list_test.go +++ b/priority_list/priority_list_test.go @@ -2,86 +2,41 @@ package plist import ( "testing" + + "github.com/Pallinder/go-randomdata" + + "github.com/emirpasic/gods/utils" ) func TestPriority(t *testing.T) { - pl := New() + pl := New(utils.IntComparator) + for i := 0; i < 20; i++ { + pl.Insert(randomdata.Number(0, 100000)) + } + t.Error(pl.String(), pl.Get(5), pl.Get(-1), pl.Get(-pl.size), pl.Get(-pl.size-1)) - pl.Insert(NewNodeInt(1)) - pl.Insert(NewNodeInt(2)) - pl.Insert(NewNodeInt(3)) - if pl.String() != "[3,2,1]" { - t.Error("Insert or String error", pl.String()) + iter := pl.Iterator() + + for iter.Next() { + t.Error(iter.Value()) } - if pl.Get(0).GetValue() != 3 { - t.Error(pl.Get(0).GetValue()) + for iter.Prev() { + t.Error(iter.Value()) } - if pl.Get(pl.Size()-1).GetValue() != 1 { - t.Error(pl.Get(pl.Size() - 1).GetValue()) - } - - if pl.Size() != 3 { - t.Error("size error, current is", pl.Size()) - } - - pl.Remove(pl.Get(2)) - if pl.String() != "[3,2]" || pl.Size() != 2 { - t.Error("Remove error current is ", pl.String(), pl.Size()) - } - - pl.Remove(pl.GetReverse(0)) - if pl.String() != "[3]" || pl.Size() != 1 { - t.Error("Remove error current is ", pl.String(), pl.Size()) - } - - pl.Remove(pl.Get(0)) - if pl.String() != "[]" || pl.Size() != 0 { - t.Error("Remove error current is ", pl.String(), pl.Size()) - } - - pl.Insert(NewNodeInt(6)) - pl.Insert(NewNodeInt(5)) - pl.Insert(NewNodeInt(7)) - pl.Insert(NewNodeInt(12)) - pl.Insert(NewNodeInt(8)) - if pl.String() != "[12,8,7,6,5]" || pl.Size() != 5 { - t.Error("Insert or String error, current is ", pl.String(), pl.Size()) - } - - pl.RemoveReverseIndex(3) - if pl.String() != "[12,7,6,5]" || pl.Size() != 4 { - t.Error("Remove error current is ", pl.String(), pl.Size()) - } - - size := pl.Size() - for i := 0; i < size; i++ { - pl.RemoveReverseIndex(0) - } - if pl.String() != "[]" || pl.Size() != 0 { - t.Error("Remove error current is ", pl.String(), pl.Size()) - } - - pl.Insert(NewNodeInt(6)) - pl.Insert(NewNodeInt(1)) - pl.Insert(NewNodeInt(9)) - pl.Insert(NewNodeInt(15)) - pl.Insert(NewNodeInt(12)) - pl.Insert(NewNodeInt(8)) - - if pl.GetCompare(NewNodeInt(9)).GetValue() != 9 { - t.Error(pl.String(), pl.GetCompare(NewNodeInt(9)).GetValue()) - } - - if pl.GetCompareReverse(NewNodeInt(11)).GetValue() != 12 { - t.Error(pl.String(), pl.GetCompareReverse(NewNodeInt(11)).GetValue()) - } - - pl.Clear() - - if pl.String() != "[]" || pl.Size() != 0 { - t.Error("Remove error current is ", pl.String(), pl.Size()) + for i := 0; i < 20; i++ { + pl.Remove(0) + t.Error(pl.String()) } } + +func BenchmarkPriority(b *testing.B) { + pl := New(utils.IntComparator) + + b.N = 10000 + for i := 0; i < b.N; i++ { + pl.Insert(randomdata.Number(0, 100000)) + } +}