github.com/alexandrestein/gods@v1.0.1/lists/doublylinkedlist/doublylinkedlist.go (about) 1 // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package doublylinkedlist implements the doubly-linked list. 6 // 7 // Structure is not thread safe. 8 // 9 // Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 10 package doublylinkedlist 11 12 import ( 13 "fmt" 14 "github.com/alexandrestein/gods/lists" 15 "github.com/alexandrestein/gods/utils" 16 "strings" 17 ) 18 19 func assertListImplementation() { 20 var _ lists.List = (*List)(nil) 21 } 22 23 // List holds the elements, where each element points to the next and previous element 24 type List struct { 25 first *element 26 last *element 27 size int 28 } 29 30 type element struct { 31 value interface{} 32 prev *element 33 next *element 34 } 35 36 // New instantiates a new empty list 37 func New() *List { 38 return &List{} 39 } 40 41 // Add appends a value (one or more) at the end of the list (same as Append()) 42 func (list *List) Add(values ...interface{}) { 43 for _, value := range values { 44 newElement := &element{value: value, prev: list.last} 45 if list.size == 0 { 46 list.first = newElement 47 list.last = newElement 48 } else { 49 list.last.next = newElement 50 list.last = newElement 51 } 52 list.size++ 53 } 54 } 55 56 // Append appends a value (one or more) at the end of the list (same as Add()) 57 func (list *List) Append(values ...interface{}) { 58 list.Add(values...) 59 } 60 61 // Prepend prepends a values (or more) 62 func (list *List) Prepend(values ...interface{}) { 63 // in reverse to keep passed order i.e. ["c","d"] -> Prepend(["a","b"]) -> ["a","b","c",d"] 64 for v := len(values) - 1; v >= 0; v-- { 65 newElement := &element{value: values[v], next: list.first} 66 if list.size == 0 { 67 list.first = newElement 68 list.last = newElement 69 } else { 70 list.first.prev = newElement 71 list.first = newElement 72 } 73 list.size++ 74 } 75 } 76 77 // Get returns the element at index. 78 // Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false. 79 func (list *List) Get(index int) (interface{}, bool) { 80 81 if !list.withinRange(index) { 82 return nil, false 83 } 84 85 // determine traveral direction, last to first or first to last 86 if list.size-index < index { 87 element := list.last 88 for e := list.size - 1; e != index; e, element = e-1, element.prev { 89 } 90 return element.value, true 91 } 92 element := list.first 93 for e := 0; e != index; e, element = e+1, element.next { 94 } 95 return element.value, true 96 } 97 98 // Remove removes one or more elements from the list with the supplied indices. 99 func (list *List) Remove(index int) { 100 101 if !list.withinRange(index) { 102 return 103 } 104 105 if list.size == 1 { 106 list.Clear() 107 return 108 } 109 110 var element *element 111 // determine traversal direction, last to first or first to last 112 if list.size-index < index { 113 element = list.last 114 for e := list.size - 1; e != index; e, element = e-1, element.prev { 115 } 116 } else { 117 element = list.first 118 for e := 0; e != index; e, element = e+1, element.next { 119 } 120 } 121 122 if element == list.first { 123 list.first = element.next 124 } 125 if element == list.last { 126 list.last = element.prev 127 } 128 if element.prev != nil { 129 element.prev.next = element.next 130 } 131 if element.next != nil { 132 element.next.prev = element.prev 133 } 134 135 element = nil 136 137 list.size-- 138 } 139 140 // Contains check if values (one or more) are present in the set. 141 // All values have to be present in the set for the method to return true. 142 // Performance time complexity of n^2. 143 // Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. 144 func (list *List) Contains(values ...interface{}) bool { 145 146 if len(values) == 0 { 147 return true 148 } 149 if list.size == 0 { 150 return false 151 } 152 for _, value := range values { 153 found := false 154 for element := list.first; element != nil; element = element.next { 155 if element.value == value { 156 found = true 157 break 158 } 159 } 160 if !found { 161 return false 162 } 163 } 164 return true 165 } 166 167 // Values returns all elements in the list. 168 func (list *List) Values() []interface{} { 169 values := make([]interface{}, list.size, list.size) 170 for e, element := 0, list.first; element != nil; e, element = e+1, element.next { 171 values[e] = element.value 172 } 173 return values 174 } 175 176 //IndexOf returns index of provided element 177 func (list *List) IndexOf(value interface{}) int { 178 if list.size == 0 { 179 return -1 180 } 181 for index, element := range list.Values() { 182 if element == value { 183 return index 184 } 185 } 186 return -1 187 } 188 // Empty returns true if list does not contain any elements. 189 func (list *List) Empty() bool { 190 return list.size == 0 191 } 192 193 // Size returns number of elements within the list. 194 func (list *List) Size() int { 195 return list.size 196 } 197 198 // Clear removes all elements from the list. 199 func (list *List) Clear() { 200 list.size = 0 201 list.first = nil 202 list.last = nil 203 } 204 205 // Sort sorts values (in-place) using. 206 func (list *List) Sort(comparator utils.Comparator) { 207 208 if list.size < 2 { 209 return 210 } 211 212 values := list.Values() 213 utils.Sort(values, comparator) 214 215 list.Clear() 216 217 list.Add(values...) 218 219 } 220 221 // Swap swaps values of two elements at the given indices. 222 func (list *List) Swap(i, j int) { 223 if list.withinRange(i) && list.withinRange(j) && i != j { 224 var element1, element2 *element 225 for e, currentElement := 0, list.first; element1 == nil || element2 == nil; e, currentElement = e+1, currentElement.next { 226 switch e { 227 case i: 228 element1 = currentElement 229 case j: 230 element2 = currentElement 231 } 232 } 233 element1.value, element2.value = element2.value, element1.value 234 } 235 } 236 237 // Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. 238 // Does not do anything if position is negative or bigger than list's size 239 // Note: position equal to list's size is valid, i.e. append. 240 func (list *List) Insert(index int, values ...interface{}) { 241 242 if !list.withinRange(index) { 243 // Append 244 if index == list.size { 245 list.Add(values...) 246 } 247 return 248 } 249 250 list.size += len(values) 251 252 var beforeElement *element 253 var foundElement *element 254 // determine traversal direction, last to first or first to last 255 if list.size-index < index { 256 foundElement = list.last 257 for e := list.size - 1; e != index; e, foundElement = e-1, foundElement.prev { 258 beforeElement = foundElement.prev 259 } 260 } else { 261 foundElement = list.first 262 for e := 0; e != index; e, foundElement = e+1, foundElement.next { 263 beforeElement = foundElement 264 } 265 } 266 267 if foundElement == list.first { 268 oldNextElement := list.first 269 for i, value := range values { 270 newElement := &element{value: value} 271 if i == 0 { 272 list.first = newElement 273 } else { 274 newElement.prev = beforeElement 275 beforeElement.next = newElement 276 } 277 beforeElement = newElement 278 } 279 oldNextElement.prev = beforeElement 280 beforeElement.next = oldNextElement 281 } else { 282 oldNextElement := beforeElement.next 283 for _, value := range values { 284 newElement := &element{value: value} 285 newElement.prev = beforeElement 286 beforeElement.next = newElement 287 beforeElement = newElement 288 } 289 oldNextElement.prev = beforeElement 290 beforeElement.next = oldNextElement 291 } 292 } 293 294 // String returns a string representation of container 295 func (list *List) String() string { 296 str := "DoublyLinkedList\n" 297 values := []string{} 298 for element := list.first; element != nil; element = element.next { 299 values = append(values, fmt.Sprintf("%v", element.value)) 300 } 301 str += strings.Join(values, ", ") 302 return str 303 } 304 305 // Check that the index is within bounds of the list 306 func (list *List) withinRange(index int) bool { 307 return index >= 0 && index < list.size 308 }