github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/lists/singlylinkedlist/singlylinkedlist.go (about)

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