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  }