From 4b5b902e65409b49357e94001f2354ef9360d1f6 Mon Sep 17 00:00:00 2001 From: huangsimin Date: Thu, 6 Dec 2018 10:36:11 +0800 Subject: [PATCH] v0.0.1 --- .gitignore | 2 + circular_linked/circular_linked.go | 239 ++++++++++++++++++++++++ circular_linked/circular_linked_test.go | 1 + 3 files changed, 242 insertions(+) create mode 100644 .gitignore create mode 100644 circular_linked/circular_linked.go create mode 100644 circular_linked/circular_linked_test.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..edd36a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +main +*.debug diff --git a/circular_linked/circular_linked.go b/circular_linked/circular_linked.go new file mode 100644 index 0000000..714442e --- /dev/null +++ b/circular_linked/circular_linked.go @@ -0,0 +1,239 @@ +package circular_linked + +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 +} + +// 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 new file mode 100644 index 0000000..980014b --- /dev/null +++ b/circular_linked/circular_linked_test.go @@ -0,0 +1 @@ +package circular_linked