github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/cols/linklist/list.go (about) 1 package linklist 2 3 import ( 4 "github.com/djordje200179/extendedlibrary/datastructures/cols" 5 "github.com/djordje200179/extendedlibrary/datastructures/iter" 6 "github.com/djordje200179/extendedlibrary/misc/functions/predication" 7 ) 8 9 // List is a doubly linked list implementation. 10 // The zero value is ready to use. Do not copy a non-zero List. 11 type List[T any] struct { 12 head, tail *Node[T] 13 size int 14 } 15 16 // New creates an empty list. 17 func New[T any]() *List[T] { 18 return new(List[T]) 19 } 20 21 // NewFromIterable creates a list from the specified iter.Iterable. 22 func NewFromIterable[T any](iterable iter.Iterable[T]) *List[T] { 23 list := New[T]() 24 25 for it := iterable.Iterator(); it.Valid(); it.Move() { 26 val := it.Get() 27 list.Append(val) 28 } 29 30 return list 31 } 32 33 // Size returns the number of elements in the list. 34 func (list *List[T]) Size() int { 35 return list.size 36 } 37 38 // GetNode returns the node at the specified index. 39 // Negative indices are interpreted as relative to the end of the List. 40 // Panics if the index is out of bounds. 41 func (list *List[T]) GetNode(index int) *Node[T] { 42 if index >= list.size || index < -list.size { 43 panic(cols.IndexOutOfBoundsError{Index: index, Length: list.size}) 44 } 45 46 if index == 0 { 47 return list.head 48 } 49 50 var curr *Node[T] 51 if index > 0 { 52 curr = list.head 53 for range index { 54 curr = curr.next 55 } 56 } else { 57 curr = list.tail 58 for i := -1; i > index; i-- { 59 curr = curr.prev 60 } 61 } 62 return curr 63 } 64 65 // GetRef returns a reference to the element at the specified index. 66 // Negative indices are interpreted as relative to the end of the List. 67 // Panics if the index is out of bounds. 68 func (list *List[T]) GetRef(index int) *T { 69 node := list.GetNode(index) 70 return &node.Value 71 } 72 73 // Get returns the element at the specified index. 74 // Negative indices are interpreted as relative to the end of the List. 75 // Panics if the index is out of bounds. 76 func (list *List[T]) Get(index int) T { 77 node := list.GetNode(index) 78 return node.Value 79 } 80 81 // Set sets the element at the specified index. 82 // Negative indices are interpreted as relative to the end of the List. 83 // Panics if the index is out of bounds. 84 func (list *List[T]) Set(index int, value T) { 85 node := list.GetNode(index) 86 node.Value = value 87 } 88 89 // Prepend inserts the specified element at the beginning of the List. 90 func (list *List[T]) Prepend(value T) { 91 if list.size == 0 { 92 node := &Node[T]{ 93 Value: value, 94 list: list, 95 } 96 97 list.head = node 98 list.tail = node 99 list.size++ 100 } else { 101 list.head.InsertBefore(value) 102 } 103 } 104 105 // Append inserts the specified element at the end of the List. 106 func (list *List[T]) Append(value T) { 107 if list.size == 0 { 108 node := &Node[T]{ 109 Value: value, 110 list: list, 111 } 112 113 list.head = node 114 list.tail = node 115 list.size++ 116 } else { 117 list.tail.InsertAfter(value) 118 } 119 } 120 121 // Insert inserts the specified element at the specified index. 122 // Negative indices are interpreted as relative to the end of the List. 123 // Panics if the index is out of bounds. 124 func (list *List[T]) Insert(index int, value T) { 125 list.GetNode(index).InsertBefore(value) 126 } 127 128 // Remove removes the element at the specified index. 129 // Negative indices are interpreted as relative to the end of the List. 130 // Panics if the index is out of bounds. 131 func (list *List[T]) Remove(index int) { 132 node := list.GetNode(index) 133 list.RemoveNode(node) 134 } 135 136 // RemoveNode removes the specified node from the List. 137 // Panics if the node is not part of the List. 138 func (list *List[T]) RemoveNode(node *Node[T]) { 139 if node == nil || node.list != list { 140 panic("invalid node") 141 } 142 143 if node.prev != nil { 144 node.prev.next = node.next 145 } else { 146 list.head = node.next 147 } 148 149 if node.next != nil { 150 node.next.prev = node.prev 151 } else { 152 list.tail = node.prev 153 } 154 155 list.size-- 156 } 157 158 // Clear removes all elements from the List. 159 func (list *List[T]) Clear() { 160 list.head = nil 161 list.tail = nil 162 list.size = 0 163 } 164 165 // Reverse reverses the order of the elements in the List. 166 func (list *List[T]) Reverse() { 167 for curr := list.head; curr != nil; curr = curr.prev { 168 curr.prev, curr.next = curr.next, curr.prev 169 } 170 171 list.head, list.tail = list.tail, list.head 172 } 173 174 // Join appends all elements from the other collection to the List. 175 // The other collection is cleared. 176 func (list *List[T]) Join(other cols.Collection[T]) { 177 switch second := other.(type) { 178 case *List[T]: 179 for curr := second.head; curr != nil; curr = curr.next { 180 curr.list = list 181 } 182 183 list.tail.next = second.head 184 second.head.prev = list.tail 185 list.tail = second.tail 186 187 list.size += second.size 188 default: 189 for it := other.Iterator(); it.Valid(); it.Move() { 190 list.Append(it.Get()) 191 } 192 } 193 194 other.Clear() 195 } 196 197 // Clone returns a shallow copy of the List. 198 func (list *List[T]) Clone() cols.Collection[T] { 199 cloned := New[T]() 200 for curr := list.head; curr != nil; curr = curr.next { 201 cloned.Append(curr.Value) 202 } 203 204 return cloned 205 } 206 207 // Iterator returns an iterator over the elements in the List. 208 func (list *List[T]) Iterator() iter.Iterator[T] { 209 return list.CollectionIterator() 210 } 211 212 // CollectionIterator returns an iterator over the elements in the List. 213 func (list *List[T]) CollectionIterator() cols.Iterator[T] { 214 return &Iterator[T]{ 215 list: list, 216 curr: list.head, 217 index: 0, 218 } 219 } 220 221 // Stream streams the elements in the List. 222 func (list *List[T]) Stream(yield func(T) bool) { 223 for curr := list.head; curr != nil; curr = curr.next { 224 if !yield(curr.Value) { 225 return 226 } 227 } 228 } 229 230 // RefsStream streams references to the elements in the List. 231 func (list *List[T]) RefsStream(yield func(*T) bool) { 232 for curr := list.head; curr != nil; curr = curr.next { 233 if !yield(&curr.Value) { 234 return 235 } 236 } 237 } 238 239 // FindIndex returns the index of the first element that matches the specified predicate. 240 func (list *List[T]) FindIndex(predicate predication.Predicate[T]) (int, bool) { 241 for curr, i := list.head, 0; curr != nil; curr, i = curr.next, i+1 { 242 if predicate(curr.Value) { 243 return i, true 244 } 245 } 246 247 return -1, false 248 } 249 250 // FindRef returns a reference to the first element that matches the specified predicate. 251 func (list *List[T]) FindRef(predicate predication.Predicate[T]) (*T, bool) { 252 node, ok := list.FindNode(predicate) 253 if !ok { 254 return nil, false 255 } 256 257 return &node.Value, true 258 } 259 260 // FindNode returns the first node that matches the specified predicate. 261 func (list *List[T]) FindNode(predicate predication.Predicate[T]) (*Node[T], bool) { 262 for curr := list.head; curr != nil; curr = curr.next { 263 if predicate(curr.Value) { 264 return curr, true 265 } 266 } 267 268 return nil, false 269 } 270 271 // Head returns the first node in the List. 272 func (list *List[T]) Head() *Node[T] { 273 return list.head 274 } 275 276 // Tail returns the last node in the List. 277 func (list *List[T]) Tail() *Node[T] { 278 return list.tail 279 }