简单的环实现,也就是首尾相接的双向链表

    1. // src/container/ring/ring.go ---- line 8
    2. // A Ring is an element of a circular list, or ring.
    3. // Rings do not have a beginning or end; a pointer to any ring element
    4. // serves as reference to the entire ring. Empty rings are represented
    5. // as nil Ring pointers. The zero value for a Ring is a one-element
    6. // ring with a nil Value.
    7. //
    8. type Ring struct {
    9. next, prev *Ring
    10. Value interface{} // for use by client; untouched by this library
    11. }

    理所当然的结构体


    比较有意思的是 MoveLinkUnlink 三个方法

    1. // src/container/ring/ring.go ---- line 41
    2. // Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0)
    3. // in the ring and returns that ring element. r must not be empty.
    4. //
    5. func (r *Ring) Move(n int) *Ring {
    6. if r.next == nil {
    7. return r.init()
    8. }
    9. switch {
    10. case n < 0:
    11. for ; n < 0; n++ {
    12. r = r.prev
    13. }
    14. case n > 0:
    15. for ; n > 0; n-- {
    16. r = r.next
    17. }
    18. }
    19. return r
    20. }
    21. // src/container/ring/ring.go ---- line 77
    22. // Link connects ring r with ring s such that r.Next()
    23. // becomes s and returns the original value for r.Next().
    24. // r must not be empty.
    25. //
    26. // If r and s point to the same ring, linking
    27. // them removes the elements between r and s from the ring.
    28. // The removed elements form a subring and the result is a
    29. // reference to that subring (if no elements were removed,
    30. // the result is still the original value for r.Next(),
    31. // and not nil).
    32. //
    33. // If r and s point to different rings, linking
    34. // them creates a single ring with the elements of s inserted
    35. // after r. The result points to the element following the
    36. // last element of s after insertion.
    37. //
    38. func (r *Ring) Link(s *Ring) *Ring {
    39. n := r.Next()
    40. if s != nil {
    41. p := s.Prev()
    42. // Note: Cannot use multiple assignment because
    43. // evaluation order of LHS is not specified.
    44. r.next = s
    45. s.prev = r
    46. n.prev = p
    47. p.next = n
    48. }
    49. return n
    50. }
    51. // Unlink removes n % r.Len() elements from the ring r, starting
    52. // at r.Next(). If n % r.Len() == 0, r remains unchanged.
    53. // The result is the removed subring. r must not be empty.
    54. //
    55. func (r *Ring) Unlink(n int) *Ring {
    56. if n <= 0 {
    57. return nil
    58. }
    59. return r.Link(r.Move(n + 1))
    60. }

    Move 倒是很简单,是因为 Unlink 用到了所以也贴出来。


    Link 对参数是单节点或多节点环都能正常工作,非常神奇。而用语言描述清楚这个过程对表达能力不强的我似乎有些为难,还是画图直观些。
    Screenshot from 2020-04-19 22-50-04.png
    Screenshot from 2020-04-19 22-50-34.png
    图中的 1,2,3,4 就分别是那四条语句建立的链接,而带 ‘ 的是指它们对应的原来的链接。在图一中因为 s 是单节点所以 s.Prev() 也就是 p 其实就是 s 所以画在一起


    至于 Unlink 方法。假设参数 n 等于 2 即需要移出后两个节点
    Screenshot from 2020-04-19 23-03-19.png
    r.Move(n+1) 标出来之后就是 Link


    还有比较有趣的一点是,结构体 Ring 的几乎所有方法(除了 LenDo)都返回 Ring 指针,所以可以链式调用