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  }