github.com/Nigel2392/go-datastructures@v1.1.5/linkedlist/doubly.go (about) 1 package linkedlist 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 ) 8 9 // A doubly linked list. 10 // 11 // This is a generic type, so you can use it with any type. 12 // 13 // For example, Doubly[int] is a linked list of integers. 14 // 15 // If using an uncomparable type, the Remove(value) method will not work. 16 // 17 // You can only use RemoveIndex(index). 18 type Doubly[T any] struct { 19 head *DoublyNode[T] 20 tail *DoublyNode[T] 21 len int 22 } 23 24 // Returns the length of the list. 25 func (l *Doubly[T]) Len() int { 26 return l.len 27 } 28 29 // Returns the list as a string. 30 func (l *Doubly[T]) String() string { 31 if l.len == 0 { 32 return "[]" 33 } 34 var b strings.Builder 35 b.WriteString("[") 36 for n := l.head; n != nil; n = n.next { 37 fmt.Fprintf(&b, "%v", n.value) 38 if n.next != nil { 39 b.WriteString(", ") 40 } 41 } 42 b.WriteString("]") 43 return b.String() 44 } 45 46 // Returns the head of the list. 47 func (l *Doubly[T]) Head() *DoublyNode[T] { 48 return l.head 49 } 50 51 // Returns the tail of the list. 52 func (l *Doubly[T]) Tail() *DoublyNode[T] { 53 return l.tail 54 } 55 56 // Append a value to the end of the list. 57 func (l *Doubly[T]) Append(v T) { 58 l.append(&DoublyNode[T]{value: v}) 59 } 60 61 // Prepend a value to the beginning of the list. 62 func (l *Doubly[T]) Prepend(v T) { 63 l.prepend(&DoublyNode[T]{value: v}) 64 } 65 66 // Pop a value from the end of the list. 67 // 68 // Returns the value that was popped. 69 // 70 // Returns the zero value of the type if the list is empty. 71 func (l *Doubly[T]) Pop() T { 72 if l.len == 0 { 73 panic("cannot Pop() from an empty list") 74 } 75 var v = l.tail.value 76 l.RemoveIndex(l.len - 1) 77 return v 78 } 79 80 // Shift a value from the beginning of the list. 81 // 82 // Returns the value that was shifted. 83 // 84 // Returns the zero value of the type if the list is empty. 85 func (l *Doubly[T]) Shift() T { 86 if l.len == 0 { 87 panic("cannot Shift() from an empty list") 88 } 89 var v = l.head.value 90 l.RemoveIndex(0) 91 return v 92 } 93 94 // Reset the list. 95 func (l *Doubly[T]) Reset() { 96 l.head = nil 97 l.tail = nil 98 l.len = 0 99 } 100 101 // Remove a value from the list at a given index. 102 func (l *Doubly[T]) RemoveIndex(i int) bool { 103 if i < 0 || i >= l.len { 104 return false 105 } 106 107 if i == 0 { 108 l.remove(i, l.head) 109 return true 110 } 111 112 if i == l.len-1 { 113 l.remove(i, l.tail) 114 return true 115 } 116 117 var n *DoublyNode[T] 118 if i < l.len/2 { 119 n = l.head 120 for j := 0; j < i; j++ { 121 n = n.next 122 } 123 } else { 124 n = l.tail 125 for j := l.len - 1; j > i; j-- { 126 n = n.prev 127 } 128 } 129 if n != nil { 130 l.remove(i, n) 131 return true 132 } 133 return false 134 } 135 136 // Returns the list as a slice. 137 func (l *Doubly[T]) ToSlice() []T { 138 if l.len == 0 { 139 return nil 140 } 141 var slice = make([]T, l.len) 142 var i = 0 143 for n := l.head; n != nil; n = n.next { 144 slice[i] = n.value 145 i++ 146 } 147 return slice 148 } 149 150 // Remove a value from the list if the predicate returns true. 151 // 152 // Returns the number of values removed. 153 func (l *Doubly[T]) RemoveIf(predicate func(T) bool) int { 154 var removed = 0 155 var i = 0 156 for n := l.head; n != nil; n = n.next { 157 if predicate(n.value) { 158 l.remove(i, n) 159 removed++ 160 } 161 i++ 162 } 163 return removed 164 } 165 166 // Remove a single value from the list. 167 // 168 // Returns true if the value was removed. 169 func (l *Doubly[T]) Remove(predicate func(value T) bool) bool { 170 var i = 0 171 for n := l.head; n != nil; n = n.next { 172 if predicate(n.value) { 173 l.remove(i, n) 174 return true 175 } 176 i++ 177 } 178 return false 179 } 180 181 // MarshalJSON implements the json.Marshaler interface. 182 func (l *Doubly[T]) MarshalJSON() ([]byte, error) { 183 return json.Marshal(l.ToSlice()) 184 } 185 186 // UnmarshalJSON implements the json.Unmarshaler interface. 187 func (l *Doubly[T]) UnmarshalJSON(data []byte) error { 188 var slice []T 189 if err := json.Unmarshal(data, &slice); err != nil { 190 return err 191 } 192 for _, v := range slice { 193 l.Append(v) 194 } 195 return nil 196 } 197 198 func (l *Doubly[T]) append(n *DoublyNode[T]) { 199 if l.head == nil && l.tail == nil { 200 l.head = n 201 l.tail = n 202 } else { 203 var oldTail = l.tail 204 l.tail = n 205 l.tail.prev = oldTail 206 oldTail.next = l.tail 207 } 208 l.len++ 209 } 210 211 func (l *Doubly[T]) prepend(n *DoublyNode[T]) { 212 if l.head == nil && l.tail == nil { 213 l.head = n 214 l.tail = n 215 } else { 216 var oldHead = l.head 217 l.head = n 218 l.head.next = oldHead 219 oldHead.prev = l.head 220 } 221 l.len++ 222 } 223 224 // remove removes a node from the list. 225 func (l *Doubly[T]) remove(i int, n *DoublyNode[T]) { 226 if i == 0 { 227 l.head = n.next 228 } 229 if i == l.len-1 { 230 l.tail = n.prev 231 } 232 233 if n.prev != nil { 234 n.prev.next = n.next 235 } 236 if n.next != nil { 237 n.next.prev = n.prev 238 } 239 l.len-- 240 }