-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathring.go
187 lines (165 loc) · 4.42 KB
/
ring.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Package ring implements a doubly-linked circular chain of data items,
// called a "ring".
package ring
import (
"fmt"
)
// A Ring is a doubly-linked circular chain of data items. There is no
// designated beginning or end of a ring; each element is a valid entry point
// for the entire ring. A ring with no elements is represented as nil.
type Ring[T any] struct {
Value T
prev, next *Ring[T]
}
func (r *Ring[T]) ptr(p *Ring[T]) string {
if p == nil {
return "-"
} else if p == r {
return "@"
} else {
return "*"
}
}
func (r *Ring[T]) String() string {
if r == nil {
return "Ring(empty)"
}
return fmt.Sprintf("Ring(%v, %v%v)", r.Value, r.ptr(r.prev), r.ptr(r.next))
}
// New constructs a new ring with n zero-valued elements.
// If n ≤ 0, New returns nil.
func New[T any](n int) *Ring[T] {
if n <= 0 {
return nil
}
r := newRing[T]()
for n > 1 {
elt := newRing[T]()
elt.next = r.next
r.next.prev = elt
elt.prev = r
r.next = elt
n--
}
return r
}
// Of constructs a new ring containing the given elements.
func Of[T any](vs ...T) *Ring[T] {
r := New[T](len(vs))
cur := r
for _, v := range vs {
cur.Value = v
cur = cur.Next()
}
return r
}
// Join splices ring s into a non-empty ring r. There are two cases:
//
// If r and s belong to different rings, [r1 ... rn] and [s1 ... sm], the
// elements of s are spliced in after r1 and the resulting ring is:
//
// [r1 s1 ... sm r2 ... rn]
// ^^^^^^^^^
//
// In this case Join returns the ring [r2 ... rn r1 ... sm].
//
// If r and s belong to the same ring, [r1 r2 ... ri s1 ... sm ... rn], then
// the loop of the ring from r2 ... ri is spliced out of r and the resulting
// ring is:
//
// [r1 s1 ... sm ... rn]
//
// In this case Join returns the ring [r2 ... ri] that was spliced out. This
// may be empty (nil) if there were no elements between r1 and s1.
func (r *Ring[T]) Join(s *Ring[T]) *Ring[T] {
if r == s || r.next == s {
return nil // same ring, no elements between r and s to remove
}
rnext, sprev := r.next, s.prev
r.next = s // successor of r is now s
s.prev = r // predecessor of s is now r
sprev.next = rnext // successor of s end is now rnext
rnext.prev = sprev // predecessor of rnext is now s end
return rnext
}
// Pop detaches r from its ring, leaving it linked only to itself.
// It returns r to permit method chaining.
func (r *Ring[T]) Pop() *Ring[T] {
if r != nil && r.prev != r {
rprev, rnext := r.prev, r.next
rprev.next = r.next
rnext.prev = r.prev
r.prev = r
r.next = r
}
return r
}
// Next returns the successor of r (which may be r itself).
// This will panic if r == nil.
func (r *Ring[T]) Next() *Ring[T] { return r.next }
// Prev returns the predecessor of r (which may be r itself).
// This will panic if r == nil.
func (r *Ring[T]) Prev() *Ring[T] { return r.prev }
// At returns the entry at offset n from r. Negative values of n are
// permitted, and r.At(0) == r. If r == nil or the absolute value of n is
// greater than the length of the ring, At returns nil.
func (r *Ring[T]) At(n int) *Ring[T] {
if r == nil {
return nil
}
next := (*Ring[T]).Next
if n < 0 {
n = -n
next = (*Ring[T]).Prev
}
cur := r
for n > 0 {
cur = next(cur)
if cur == r {
return nil
}
n--
}
return cur
}
// Peek reports whether the ring has a value at offset n from r, and if so
// returns its value. Negative values of n are permitted. If the absolute value
// of n is greater than the length of the ring, Peek reports a zero value.
func (r *Ring[T]) Peek(n int) (T, bool) {
cur := r.At(n)
if cur == nil {
var zero T
return zero, false
}
return cur.Value, true
}
// Each is a range function that calls f with each value of r in circular
// order. If f returns false, Each returns immediately.
func (r *Ring[T]) Each(f func(v T) bool) {
scan(r, func(cur *Ring[T]) bool { return f(cur.Value) })
}
// Len reports the number of elements in r. If r == nil, Len is 0.
// This operation takes time proportional to the size of the ring.
func (r *Ring[T]) Len() int {
if r == nil {
return 0
}
var n int
scan(r, func(*Ring[T]) bool { n++; return true })
return n
}
// IsEmpty reports whether r is the empty ring.
func (r *Ring[T]) IsEmpty() bool { return r == nil }
func scan[T any](r *Ring[T], f func(*Ring[T]) bool) {
if r == nil {
return
}
cur := r
for f(cur) {
if cur.next == r {
return
}
cur = cur.next
}
}
func newRing[T any]() *Ring[T] { r := new(Ring[T]); r.next = r; r.prev = r; return r }