github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/cols/linklist/sorting.go (about)

     1  package linklist
     2  
     3  import (
     4  	"github.com/djordje200179/extendedlibrary/misc/functions/comparison"
     5  )
     6  
     7  // Sort sorts the elements in the List by the specified comparator.
     8  // The sorting algorithm is a stable variant of merge sort.
     9  func (list *List[T]) Sort(comparator comparison.Comparator[T]) {
    10  	if list == nil || list.head == nil || list.head.next == nil {
    11  		return
    12  	}
    13  
    14  	firstList, secondList := splitList(list)
    15  
    16  	firstList.Sort(comparator)
    17  	secondList.Sort(comparator)
    18  
    19  	sortedMerge(firstList, secondList, list, comparator)
    20  }
    21  
    22  func sortedMerge[T any](firstList, secondList, resultList *List[T], comparator comparison.Comparator[T]) {
    23  	if firstList == nil {
    24  		*resultList = *secondList
    25  	}
    26  
    27  	if secondList == nil {
    28  		*resultList = *firstList
    29  	}
    30  
    31  	resultList.Clear()
    32  
    33  	firstListCurr := firstList.head
    34  	secondListCurr := secondList.head
    35  
    36  	for firstListCurr != nil && secondListCurr != nil {
    37  		if comparator(firstListCurr.Value, secondListCurr.Value) == comparison.FirstSmaller {
    38  			resultList.Append(firstListCurr.Value)
    39  			firstListCurr = firstListCurr.next
    40  		} else {
    41  			resultList.Append(secondListCurr.Value)
    42  			secondListCurr = secondListCurr.next
    43  		}
    44  	}
    45  
    46  	for firstListCurr != nil {
    47  		resultList.Append(firstListCurr.Value)
    48  		firstListCurr = firstListCurr.next
    49  	}
    50  
    51  	for secondListCurr != nil {
    52  		resultList.Append(secondListCurr.Value)
    53  		secondListCurr = secondListCurr.next
    54  	}
    55  }
    56  
    57  func splitList[T any](list *List[T]) (*List[T], *List[T]) {
    58  	middleIndex := list.Size() / 2
    59  	middleNode := list.GetNode(middleIndex - 1)
    60  
    61  	firstList := &List[T]{
    62  		head: list.head,
    63  		tail: middleNode,
    64  		size: middleIndex,
    65  	}
    66  
    67  	secondList := &List[T]{
    68  		head: middleNode.next,
    69  		tail: list.tail,
    70  		size: list.Size() - middleIndex,
    71  	}
    72  
    73  	middleNode.next.prev = nil
    74  	middleNode.next = nil
    75  
    76  	list.Clear()
    77  
    78  	return firstList, secondList
    79  }