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 }