github.com/benz9527/toy-box/algo@v0.0.0-20240221120937-66c0c6bd5abd/list/doubly_linkedlist.go (about)

     1  package list
     2  
     3  import (
     4  	"sync/atomic"
     5  )
     6  
     7  var (
     8  	_ LinkedList[struct{}] = (*doublyLinkedList[struct{}])(nil) // Type check assertion
     9  )
    10  
    11  type nodeElementInListStatus uint8
    12  
    13  const (
    14  	notInList nodeElementInListStatus = iota
    15  	emtpyList
    16  	theOnlyOne
    17  	theFirstButNotTheLast
    18  	theLastButNotTheFirst
    19  	inMiddle
    20  )
    21  
    22  type doublyLinkedList[T comparable] struct {
    23  	root nodeElement[T]
    24  	len  atomic.Int64
    25  }
    26  
    27  func NewLinkedList[T comparable]() LinkedList[T] {
    28  	return new(doublyLinkedList[T]).init()
    29  }
    30  
    31  func (l *doublyLinkedList[T]) getRoot() NodeElement[T] {
    32  	return &l.root
    33  }
    34  
    35  func (l *doublyLinkedList[T]) getRootHead() NodeElement[T] {
    36  	return l.root.next
    37  }
    38  
    39  func (l *doublyLinkedList[T]) setRootHead(targetE NodeElement[T]) {
    40  	l.root.next = targetE
    41  }
    42  
    43  func (l *doublyLinkedList[T]) getRootTail() NodeElement[T] {
    44  	return l.root.prev
    45  }
    46  
    47  func (l *doublyLinkedList[T]) setRootTail(targetE NodeElement[T]) {
    48  	l.root.prev = targetE
    49  }
    50  
    51  func (l *doublyLinkedList[T]) init() *doublyLinkedList[T] {
    52  	l.root.list = l
    53  	l.setRootHead(&l.root)
    54  	l.setRootTail(&l.root)
    55  	l.len.Store(0)
    56  	return l
    57  }
    58  
    59  func (l *doublyLinkedList[T]) Len() int64 {
    60  	return l.len.Load()
    61  }
    62  
    63  func (l *doublyLinkedList[T]) checkElement(targetE NodeElement[T]) (*nodeElement[T], nodeElementInListStatus) {
    64  	if targetE == nil {
    65  		return nil, notInList
    66  	}
    67  	at, ok := targetE.(*nodeElement[T])
    68  	if !ok || at.list != l || at.hasLock() != l.root.hasLock() {
    69  		return nil, notInList
    70  	}
    71  	if l.len.Load() == 0 {
    72  		return l.getRoot().(*nodeElement[T]), emtpyList
    73  	}
    74  
    75  	// mem address compare
    76  	switch {
    77  	case at.GetPrev() == nil && at.GetNext() == nil:
    78  		// targetE is the first one and the last one
    79  		if l.getRootHead() != targetE || l.getRootTail() != targetE {
    80  			return nil, notInList
    81  		}
    82  		return at, theOnlyOne
    83  	case at.GetPrev() == nil && at.GetNext() != nil:
    84  		// targetE is the first one but not the last one
    85  		if at.GetNext().GetPrev() != targetE {
    86  			return nil, notInList
    87  		}
    88  		// Ignore l.setRootTail (tail)
    89  		return at, theFirstButNotTheLast
    90  	case at.GetPrev() != nil && at.GetNext() == nil:
    91  		// targetE is the last one but not the first one
    92  		if at.GetPrev().GetNext() != targetE {
    93  			return nil, notInList
    94  		}
    95  		// Ignore l.setRootHead (head)
    96  		return at, theLastButNotTheFirst
    97  	case at.GetPrev() != nil && at.GetNext() != nil:
    98  		// targetE is neither the first one nor the last one
    99  		if at.GetPrev().GetNext() != targetE && at.GetNext().GetPrev() != targetE {
   100  			return nil, notInList
   101  		}
   102  		return at, inMiddle
   103  	}
   104  	return nil, notInList
   105  }
   106  
   107  func (l *doublyLinkedList[T]) append(e *nodeElement[T]) NodeElement[T] {
   108  	e.list = l
   109  	e.next, e.prev = nil, nil
   110  
   111  	if l.len.Load() == 0 {
   112  		// empty list, new append element is the first one
   113  		l.setRootHead(e)
   114  		l.setRootTail(e)
   115  		l.len.Add(1)
   116  		return e
   117  	}
   118  
   119  	lastOne := l.getRootTail().(*nodeElement[T])
   120  	lastOne.next = e
   121  	e.prev, e.next = lastOne, nil
   122  	l.setRootTail(e)
   123  
   124  	l.len.Add(1)
   125  	return e
   126  }
   127  
   128  func (l *doublyLinkedList[T]) Append(elements ...NodeElement[T]) []NodeElement[T] {
   129  	if l.getRootTail() == nil {
   130  		return nil
   131  	}
   132  	for i := 0; i < len(elements); i++ {
   133  		if elements[i] == nil {
   134  			continue
   135  		}
   136  		e, ok := elements[i].(*nodeElement[T])
   137  		if !ok || e.list != l || l.root.hasLock() != e.hasLock() {
   138  			continue
   139  		}
   140  		elements[i] = l.append(e)
   141  	}
   142  	return elements
   143  }
   144  
   145  func (l *doublyLinkedList[T]) AppendValue(values ...T) []NodeElement[T] {
   146  	// FIXME How to decrease the memory allocation for each operation?
   147  	//  sync.Pool reused the released objects?
   148  	if len(values) <= 0 {
   149  		return nil
   150  	} else if len(values) == 1 {
   151  		return l.Append(newNodeElement(values[0], l))
   152  	}
   153  
   154  	newElements := make([]NodeElement[T], 0, len(values))
   155  	for _, v := range values {
   156  		newElements = append(newElements, newNodeElement(v, l))
   157  	}
   158  	return l.Append(newElements...)
   159  }
   160  
   161  func (l *doublyLinkedList[T]) insertAfter(newE, at *nodeElement[T]) *nodeElement[T] {
   162  	if at == l.getRoot() {
   163  		newE.prev = nil
   164  	} else {
   165  		newE.prev = at
   166  	}
   167  
   168  	if l.len.Load() == 0 {
   169  		newE.next = nil
   170  		l.setRootHead(newE)
   171  		l.setRootTail(newE)
   172  	} else {
   173  		newE.next = at.GetNext()
   174  		at.next = newE
   175  		if newE.GetNext() != nil {
   176  			newE.GetNext().(*nodeElement[T]).prev = newE
   177  		}
   178  	}
   179  	l.len.Add(1)
   180  	return newE
   181  }
   182  
   183  func (l *doublyLinkedList[T]) InsertAfter(v T, dstE NodeElement[T]) NodeElement[T] {
   184  	at, status := l.checkElement(dstE)
   185  	if status == notInList {
   186  		return nil
   187  	}
   188  
   189  	newE := newNodeElement(v, l)
   190  	newE = l.insertAfter(newE, at)
   191  	switch status {
   192  	case theOnlyOne, theLastButNotTheFirst:
   193  		l.setRootTail(newE)
   194  	default:
   195  
   196  	}
   197  	return newE
   198  }
   199  
   200  func (l *doublyLinkedList[T]) insertBefore(newE, at *nodeElement[T]) *nodeElement[T] {
   201  	if at == l.getRoot() {
   202  		newE.next = nil
   203  	} else {
   204  		newE.next = at
   205  	}
   206  	if l.len.Load() == 0 {
   207  		newE.prev = nil
   208  		l.setRootHead(newE)
   209  		l.setRootTail(newE)
   210  	} else {
   211  		newE.prev = at.prev
   212  		at.prev = newE
   213  		if newE.GetPrev() != nil {
   214  			newE.GetPrev().(*nodeElement[T]).next = newE
   215  		}
   216  	}
   217  	l.len.Add(1)
   218  	return newE
   219  }
   220  
   221  func (l *doublyLinkedList[T]) InsertBefore(v T, dstE NodeElement[T]) NodeElement[T] {
   222  	at, status := l.checkElement(dstE)
   223  	if status == notInList {
   224  		return nil
   225  	}
   226  	newE := newNodeElement(v, l)
   227  	newE = l.insertBefore(newE, at)
   228  	switch status {
   229  	case theOnlyOne, theFirstButNotTheLast:
   230  		l.setRootHead(newE)
   231  	default:
   232  
   233  	}
   234  	return newE
   235  }
   236  
   237  func (l *doublyLinkedList[T]) Remove(targetE NodeElement[T]) NodeElement[T] {
   238  	var (
   239  		at     *nodeElement[T]
   240  		status nodeElementInListStatus
   241  	)
   242  
   243  	// doubly linked list removes element is free to do iteration, but we have to check the value if equals.
   244  	// avoid memory leaks
   245  	switch at, status = l.checkElement(targetE); status {
   246  	case theOnlyOne:
   247  		l.setRootHead(l.getRoot())
   248  		l.setRootTail(l.getRoot())
   249  	case theFirstButNotTheLast:
   250  		l.setRootHead(at.GetNext())
   251  		at.GetNext().(*nodeElement[T]).prev = nil
   252  	case theLastButNotTheFirst:
   253  		l.setRootTail(at.GetPrev())
   254  		at.GetPrev().(*nodeElement[T]).next = nil
   255  	case inMiddle:
   256  		at.GetPrev().(*nodeElement[T]).next = at.next
   257  		at.GetNext().(*nodeElement[T]).prev = at.prev
   258  	default:
   259  		return nil
   260  	}
   261  
   262  	// avoid memory leaks
   263  	at.list = nil
   264  	at.next = nil
   265  	at.prev = nil
   266  	if at.lock != nil {
   267  		at.lock = nil
   268  	}
   269  	l.len.Add(-1)
   270  	return at
   271  }
   272  
   273  func (l *doublyLinkedList[T]) ForEach(fn func(idx int64, e NodeElement[T])) {
   274  	if fn == nil || l.len.Load() == 0 ||
   275  		l.getRoot() == l.getRootHead() && l.getRoot() == l.getRootTail() {
   276  		return
   277  	}
   278  
   279  	var (
   280  		iterator       = l.getRoot().GetNext()
   281  		idx      int64 = 0
   282  	)
   283  	for iterator != nil {
   284  		// Avoid remove in iteration result in memory leak
   285  		next := iterator.GetNext()
   286  		fn(idx, iterator)
   287  		iterator, idx = next, idx+1
   288  	}
   289  }
   290  
   291  func (l *doublyLinkedList[T]) ReverseForEach(fn func(idx int64, e NodeElement[T])) {
   292  	if fn == nil || l.len.Load() == 0 ||
   293  		l.getRoot() == l.getRootHead() && l.getRoot() == l.getRootTail() {
   294  		return
   295  	}
   296  
   297  	var (
   298  		iterator       = l.getRoot().GetPrev()
   299  		idx      int64 = 0
   300  	)
   301  	for iterator != nil {
   302  		// Avoid remove in iteration result in memory leak
   303  		prev := iterator.GetPrev()
   304  		fn(idx, iterator)
   305  		iterator, idx = prev, idx+1
   306  	}
   307  }
   308  
   309  func (l *doublyLinkedList[T]) FindFirst(targetV T, compareFn ...func(e NodeElement[T]) bool) (NodeElement[T], bool) {
   310  	if l.len.Load() == 0 {
   311  		return nil, false
   312  	}
   313  
   314  	if len(compareFn) <= 0 {
   315  		compareFn = []func(e NodeElement[T]) bool{
   316  			func(e NodeElement[T]) bool {
   317  				return e.GetValue() == targetV
   318  			},
   319  		}
   320  	}
   321  
   322  	var iterator = l.getRoot()
   323  	for iterator.HasNext() {
   324  		if compareFn[0](iterator.GetNext()) {
   325  			return iterator.GetNext(), true
   326  		}
   327  		iterator = iterator.GetNext()
   328  	}
   329  	return nil, false
   330  }
   331  
   332  func (l *doublyLinkedList[T]) Front() NodeElement[T] {
   333  	return l.root.GetNext()
   334  }
   335  
   336  func (l *doublyLinkedList[T]) Back() NodeElement[T] {
   337  	return l.root.GetPrev()
   338  }
   339  
   340  func (l *doublyLinkedList[T]) PushFront(v T) NodeElement[T] {
   341  	return l.InsertBefore(v, l.getRootHead())
   342  }
   343  
   344  func (l *doublyLinkedList[T]) PushBack(v T) NodeElement[T] {
   345  	return l.InsertAfter(v, l.getRootTail())
   346  }
   347  
   348  func (l *doublyLinkedList[T]) move(src, dst *nodeElement[T]) bool {
   349  	if src == dst {
   350  		return false
   351  	}
   352  	// Ordinarily, it is move src next to dst
   353  	if src.HasPrev() { // src is not the first node
   354  		src.GetPrev().(*nodeElement[T]).next = src.next
   355  	}
   356  	if src.HasNext() { // src is not the last node
   357  		src.GetNext().(*nodeElement[T]).prev = src.prev
   358  	}
   359  
   360  	if dst == l.getRoot() { // dst is the first node
   361  		src.prev = nil
   362  	} else {
   363  		src.prev = dst
   364  	}
   365  	src.next = dst.GetNext()
   366  	if src.HasNext() { // src updated but not the last node
   367  		src.GetNext().(*nodeElement[T]).prev = src
   368  	}
   369  
   370  	dst.next = src
   371  	return true
   372  }
   373  
   374  func (l *doublyLinkedList[T]) MoveToFront(targetE NodeElement[T]) {
   375  	moved := false
   376  	src, status := l.checkElement(targetE)
   377  	switch status {
   378  	case theLastButNotTheFirst:
   379  		defer func(prev NodeElement[T]) {
   380  			if moved {
   381  				l.setRootHead(src)
   382  				l.setRootTail(prev)
   383  			}
   384  		}(src.GetPrev()) // register the element immediately
   385  	case notInList, theOnlyOne, theFirstButNotTheLast:
   386  		return
   387  	default:
   388  
   389  	}
   390  	moved = l.move(src, &l.root)
   391  }
   392  
   393  func (l *doublyLinkedList[T]) MoveToBack(targetE NodeElement[T]) {
   394  	moved := false
   395  	src, status := l.checkElement(targetE)
   396  	switch status {
   397  	case theFirstButNotTheLast:
   398  		defer func(next NodeElement[T]) {
   399  			if moved {
   400  				l.setRootHead(next)
   401  				l.setRootTail(src)
   402  			}
   403  		}(src.GetNext()) // register the element immediately
   404  	case notInList, theLastButNotTheFirst, theOnlyOne:
   405  		return
   406  	default:
   407  
   408  	}
   409  	moved = l.move(src, l.getRootTail().(*nodeElement[T]))
   410  }
   411  
   412  func (l *doublyLinkedList[T]) MoveBefore(srcE, dstE NodeElement[T]) {
   413  	var (
   414  		moved                = false
   415  		dst, src             *nodeElement[T]
   416  		dstStatus, srcStatus nodeElementInListStatus
   417  	)
   418  	switch dst, dstStatus = l.checkElement(dstE); dstStatus {
   419  	case notInList, theOnlyOne:
   420  		return
   421  	default:
   422  
   423  	}
   424  	switch src, srcStatus = l.checkElement(srcE); srcStatus {
   425  	case notInList, theOnlyOne:
   426  		return
   427  	case theFirstButNotTheLast:
   428  		defer func(next NodeElement[T]) {
   429  			// src from the head to the middle
   430  			if moved && dstStatus == theLastButNotTheFirst || dstStatus == inMiddle {
   431  				l.setRootHead(next)
   432  			}
   433  		}(src.GetNext()) // register the element immediately
   434  	case theLastButNotTheFirst:
   435  		defer func(prev NodeElement[T]) {
   436  			// src from the tail to the head
   437  			if moved && dstStatus == theFirstButNotTheLast {
   438  				l.setRootHead(src)
   439  				l.setRootTail(prev)
   440  			}
   441  			if moved && dstStatus == inMiddle {
   442  				l.setRootTail(prev)
   443  			}
   444  		}(src.GetPrev()) // register the element immediately
   445  	case inMiddle:
   446  		defer func() {
   447  			// src as the new first node
   448  			if moved && dstStatus == theFirstButNotTheLast {
   449  				l.setRootHead(src)
   450  			}
   451  		}()
   452  	default:
   453  
   454  	}
   455  	if dst.GetPrev() == nil {
   456  		return
   457  	}
   458  	dstPrev := dst.GetPrev().(*nodeElement[T])
   459  	moved = l.move(src, dstPrev)
   460  }
   461  
   462  func (l *doublyLinkedList[T]) MoveAfter(srcE, dstE NodeElement[T]) {
   463  	var (
   464  		moved                = false
   465  		dst, src             *nodeElement[T]
   466  		dstStatus, srcStatus nodeElementInListStatus
   467  	)
   468  	switch dst, dstStatus = l.checkElement(dstE); dstStatus {
   469  	case notInList, theOnlyOne:
   470  		return
   471  	default:
   472  
   473  	}
   474  	switch src, srcStatus = l.checkElement(srcE); srcStatus {
   475  	case notInList, theOnlyOne:
   476  		return
   477  	case theFirstButNotTheLast:
   478  		defer func(next NodeElement[T]) {
   479  			// src from the head to the tail
   480  			if moved && dstStatus == theLastButNotTheFirst {
   481  				l.setRootHead(next)
   482  				l.setRootTail(src)
   483  			}
   484  			// src from the head to the middle
   485  			if moved && dstStatus == inMiddle {
   486  				l.setRootHead(next)
   487  			}
   488  		}(src.GetNext()) // register the element immediately
   489  	case theLastButNotTheFirst:
   490  		defer func(prev NodeElement[T]) {
   491  			// src from the tail to the middle
   492  			if moved && dstStatus == theFirstButNotTheLast || dstStatus == inMiddle {
   493  				l.setRootTail(prev)
   494  			}
   495  		}(src.GetPrev())
   496  	case inMiddle:
   497  		defer func() {
   498  			if moved && dstStatus == theLastButNotTheFirst {
   499  				l.setRootTail(src)
   500  			}
   501  		}()
   502  	default:
   503  
   504  	}
   505  
   506  	moved = l.move(src, dst)
   507  }
   508  
   509  func (l *doublyLinkedList[T]) PushFrontList(src LinkedList[T]) {
   510  	if dl, ok := src.(*doublyLinkedList[T]); !ok || dl != nil && dl.getRoot() == l.getRoot() {
   511  		// avoid type mismatch and self copy
   512  		return
   513  	}
   514  
   515  	for i, e := src.Len(), src.Back(); i > 0; i-- {
   516  		prev := e.GetPrev()
   517  		// Clean the node element reference, not a required operation
   518  		e.(*nodeElement[T]).list = l
   519  		e.(*nodeElement[T]).prev = nil
   520  		e.(*nodeElement[T]).next = nil
   521  		l.insertAfter(e.(*nodeElement[T]), &l.root)
   522  		e = prev
   523  	}
   524  }
   525  
   526  func (l *doublyLinkedList[T]) PushBackList(src LinkedList[T]) {
   527  	if dl, ok := src.(*doublyLinkedList[T]); !ok || dl != nil && dl.getRoot() == l.getRoot() {
   528  		// avoid type mismatch and self copy
   529  		return
   530  	}
   531  	for i, e := src.Len(), src.Front(); i > 0; i-- {
   532  		next := e.GetNext()
   533  		// Clean the node element reference, not a required operation
   534  		e.(*nodeElement[T]).list = l
   535  		e.(*nodeElement[T]).prev = nil
   536  		e.(*nodeElement[T]).next = nil
   537  		l.Append(e)
   538  		e = next
   539  	}
   540  }