github.com/GoWebProd/gip@v0.0.0-20230623090727-b60d41d5d320/list/list.go (about)

     1  // Copyright 2009 The Go Authors. 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 list implements a doubly linked list.
     6  //
     7  // To iterate over a list (where l is a *List):
     8  //	for e := l.Front(); e != nil; e = e.Next() {
     9  //		// do something with e.Value
    10  //	}
    11  //
    12  package list
    13  
    14  // Element is an element of a linked list.
    15  type Element[V any] struct {
    16  	// Next and previous pointers in the doubly-linked list of elements.
    17  	// To simplify the implementation, internally a list l is implemented
    18  	// as a ring, such that &l.root is both the next element of the last
    19  	// list element (l.Back()) and the previous element of the first list
    20  	// element (l.Front()).
    21  	next, prev *Element[V]
    22  
    23  	// The list to which this element belongs.
    24  	list *List[V]
    25  
    26  	// The value stored with this element.
    27  	Value V
    28  }
    29  
    30  // Next returns the next list element or nil.
    31  func (e *Element[V]) Next() *Element[V] {
    32  	if p := e.next; e.list != nil && p != &e.list.root {
    33  		return p
    34  	}
    35  
    36  	return nil
    37  }
    38  
    39  // Prev returns the previous list element or nil.
    40  func (e *Element[V]) Prev() *Element[V] {
    41  	if p := e.prev; e.list != nil && p != &e.list.root {
    42  		return p
    43  	}
    44  
    45  	return nil
    46  }
    47  
    48  // List represents a doubly linked list.
    49  // The zero value for List is an empty list ready to use.
    50  type List[V any] struct {
    51  	root Element[V] // sentinel list element, only &root, root.prev, and root.next are used
    52  	len  int        // current list length excluding (this) sentinel element
    53  }
    54  
    55  // Init initializes or clears list l.
    56  func (l *List[V]) Init() *List[V] {
    57  	l.root.next = &l.root
    58  	l.root.prev = &l.root
    59  	l.len = 0
    60  
    61  	return l
    62  }
    63  
    64  // New returns an initialized list.
    65  func New[V any]() *List[V] {
    66  	return new(List[V]).Init()
    67  }
    68  
    69  // Len returns the number of elements of list l.
    70  // The complexity is O(1).
    71  func (l *List[V]) Len() int {
    72  	return l.len
    73  }
    74  
    75  // Front returns the first element of list l or nil if the list is empty.
    76  func (l *List[V]) Front() *Element[V] {
    77  	if l.len == 0 {
    78  		return nil
    79  	}
    80  
    81  	return l.root.next
    82  }
    83  
    84  // Back returns the last element of list l or nil if the list is empty.
    85  func (l *List[V]) Back() *Element[V] {
    86  	if l.len == 0 {
    87  		return nil
    88  	}
    89  
    90  	return l.root.prev
    91  }
    92  
    93  // lazyInit lazily initializes a zero List value.
    94  func (l *List[V]) lazyInit() {
    95  	if l.root.next == nil {
    96  		l.Init()
    97  	}
    98  }
    99  
   100  // insert inserts e after at, increments l.len, and returns e.
   101  func (l *List[V]) insert(e, at *Element[V]) *Element[V] {
   102  	e.prev = at
   103  	e.next = at.next
   104  	e.prev.next = e
   105  	e.next.prev = e
   106  	e.list = l
   107  	l.len++
   108  
   109  	return e
   110  }
   111  
   112  // insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
   113  func (l *List[V]) insertValue(v V, at *Element[V]) *Element[V] {
   114  	return l.insert(&Element[V]{Value: v}, at)
   115  }
   116  
   117  // remove removes e from its list, decrements l.len, and returns e.
   118  func (l *List[V]) remove(e *Element[V]) *Element[V] {
   119  	e.prev.next = e.next
   120  	e.next.prev = e.prev
   121  	e.next = nil // avoid memory leaks
   122  	e.prev = nil // avoid memory leaks
   123  	e.list = nil
   124  	l.len--
   125  
   126  	return e
   127  }
   128  
   129  // move moves e to next to at and returns e.
   130  func (l *List[V]) move(e, at *Element[V]) *Element[V] {
   131  	if e == at {
   132  		return e
   133  	}
   134  
   135  	e.prev.next = e.next
   136  	e.next.prev = e.prev
   137  
   138  	e.prev = at
   139  	e.next = at.next
   140  	e.prev.next = e
   141  	e.next.prev = e
   142  
   143  	return e
   144  }
   145  
   146  // Remove removes e from l if e is an element of list l.
   147  // It returns the element value e.Value.
   148  // The element must not be nil.
   149  func (l *List[V]) Remove(e *Element[V]) V {
   150  	if e.list == l {
   151  		// if e.list == l, l must have been initialized when e was inserted
   152  		// in l or l == nil (e is a zero Element) and l.remove will crash
   153  		l.remove(e)
   154  	}
   155  
   156  	return e.Value
   157  }
   158  
   159  // PushFront inserts a new element e with value v at the front of list l and returns e.
   160  func (l *List[V]) PushFront(v V) *Element[V] {
   161  	l.lazyInit()
   162  
   163  	return l.insertValue(v, &l.root)
   164  }
   165  
   166  // PushBack inserts a new element e with value v at the back of list l and returns e.
   167  func (l *List[V]) PushBack(v V) *Element[V] {
   168  	l.lazyInit()
   169  
   170  	return l.insertValue(v, l.root.prev)
   171  }
   172  
   173  // InsertBefore inserts a new element e with value v immediately before mark and returns e.
   174  // If mark is not an element of l, the list is not modified.
   175  // The mark must not be nil.
   176  func (l *List[V]) InsertBefore(v V, mark *Element[V]) *Element[V] {
   177  	if mark.list != l {
   178  		return nil
   179  	}
   180  
   181  	// see comment in List.Remove about initialization of l
   182  	return l.insertValue(v, mark.prev)
   183  }
   184  
   185  // InsertAfter inserts a new element e with value v immediately after mark and returns e.
   186  // If mark is not an element of l, the list is not modified.
   187  // The mark must not be nil.
   188  func (l *List[V]) InsertAfter(v V, mark *Element[V]) *Element[V] {
   189  	if mark.list != l {
   190  		return nil
   191  	}
   192  
   193  	// see comment in List.Remove about initialization of l
   194  	return l.insertValue(v, mark)
   195  }
   196  
   197  // MoveToFront moves element e to the front of list l.
   198  // If e is not an element of l, the list is not modified.
   199  // The element must not be nil.
   200  func (l *List[V]) MoveToFront(e *Element[V]) {
   201  	if e.list != l || l.root.next == e {
   202  		return
   203  	}
   204  
   205  	// see comment in List.Remove about initialization of l
   206  	l.move(e, &l.root)
   207  }
   208  
   209  // MoveToBack moves element e to the back of list l.
   210  // If e is not an element of l, the list is not modified.
   211  // The element must not be nil.
   212  func (l *List[V]) MoveToBack(e *Element[V]) {
   213  	if e.list != l || l.root.prev == e {
   214  		return
   215  	}
   216  
   217  	// see comment in List.Remove about initialization of l
   218  	l.move(e, l.root.prev)
   219  }
   220  
   221  // MoveBefore moves element e to its new position before mark.
   222  // If e or mark is not an element of l, or e == mark, the list is not modified.
   223  // The element and mark must not be nil.
   224  func (l *List[V]) MoveBefore(e, mark *Element[V]) {
   225  	if e.list != l || e == mark || mark.list != l {
   226  		return
   227  	}
   228  
   229  	l.move(e, mark.prev)
   230  }
   231  
   232  // MoveAfter moves element e to its new position after mark.
   233  // If e or mark is not an element of l, or e == mark, the list is not modified.
   234  // The element and mark must not be nil.
   235  func (l *List[V]) MoveAfter(e, mark *Element[V]) {
   236  	if e.list != l || e == mark || mark.list != l {
   237  		return
   238  	}
   239  
   240  	l.move(e, mark)
   241  }
   242  
   243  // PushBackList inserts a copy of another list at the back of list l.
   244  // The lists l and other may be the same. They must not be nil.
   245  func (l *List[V]) PushBackList(other *List[V]) {
   246  	l.lazyInit()
   247  
   248  	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
   249  		l.insertValue(e.Value, l.root.prev)
   250  	}
   251  }
   252  
   253  // PushFrontList inserts a copy of another list at the front of list l.
   254  // The lists l and other may be the same. They must not be nil.
   255  func (l *List[V]) PushFrontList(other *List[V]) {
   256  	l.lazyInit()
   257  
   258  	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
   259  		l.insertValue(e.Value, &l.root)
   260  	}
   261  }