mirror of
				https://github.com/duke-git/lancet.git
				synced 2025-10-31 10:46:24 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			205 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2021 dudaodong@gmail.com. All rights reserved.
 | |
| // Use of this source code is governed by MIT license
 | |
| 
 | |
| package algorithm
 | |
| 
 | |
| import "github.com/duke-git/lancet/v2/constraints"
 | |
| 
 | |
| // BubbleSort applys the bubble sort algorithm to sort the collection, will change the original collection data.
 | |
| // Play: https://go.dev/play/p/GNdv7Jg2Taj
 | |
| func BubbleSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	for i := 0; i < len(slice); i++ {
 | |
| 		breakTag := false
 | |
| 		for j := 0; j < len(slice)-1-i; j++ {
 | |
| 			isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
 | |
| 			if isCurrGreatThanNext {
 | |
| 				swap(slice, j, j+1)
 | |
| 				breakTag = true
 | |
| 			}
 | |
| 		}
 | |
| 		if !breakTag {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // InsertionSort applys the insertion sort algorithm to sort the collection, will change the original collection data.
 | |
| // Play: https://go.dev/play/p/G5LJiWgJJW6
 | |
| func InsertionSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	for i := 0; i < len(slice); i++ {
 | |
| 		for j := i; j > 0; j-- {
 | |
| 			isPreLessThanCurrent := comparator.Compare(slice[j], slice[j-1]) == -1
 | |
| 			if isPreLessThanCurrent {
 | |
| 				swap(slice, j, j-1)
 | |
| 			} else {
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // SelectionSort applys the selection sort algorithm to sort the collection, will change the original collection data.
 | |
| // Play: https://go.dev/play/p/oXovbkekayS
 | |
| func SelectionSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	for i := 0; i < len(slice); i++ {
 | |
| 		min := i
 | |
| 		for j := i + 1; j < len(slice); j++ {
 | |
| 			if comparator.Compare(slice[j], slice[min]) == -1 {
 | |
| 				min = j
 | |
| 			}
 | |
| 		}
 | |
| 		swap(slice, i, min)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // ShellSort applys the shell sort algorithm to sort the collection, will change the original collection data.
 | |
| // Play: https://go.dev/play/p/3ibkszpJEu3
 | |
| func ShellSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	size := len(slice)
 | |
| 
 | |
| 	gap := 1
 | |
| 	for gap < size/3 {
 | |
| 		gap = 3*gap + 1
 | |
| 	}
 | |
| 
 | |
| 	for gap >= 1 {
 | |
| 		for i := gap; i < size; i++ {
 | |
| 			for j := i; j >= gap && comparator.Compare(slice[j], slice[j-gap]) == -1; j -= gap {
 | |
| 				swap(slice, j, j-gap)
 | |
| 			}
 | |
| 		}
 | |
| 		gap = gap / 3
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1.
 | |
| // Play: https://go.dev/play/p/7Y7c1Elk3ax
 | |
| func QuickSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	quickSort(slice, 0, len(slice)-1, comparator)
 | |
| }
 | |
| 
 | |
| func quickSort[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
 | |
| 	if lowIndex < highIndex {
 | |
| 		p := partition(slice, lowIndex, highIndex, comparator)
 | |
| 		quickSort(slice, lowIndex, p-1, comparator)
 | |
| 		quickSort(slice, p+1, highIndex, comparator)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // partition split slice into two parts
 | |
| func partition[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) int {
 | |
| 	p := slice[highIndex]
 | |
| 	i := lowIndex
 | |
| 	for j := lowIndex; j < highIndex; j++ {
 | |
| 		if comparator.Compare(slice[j], p) == -1 { //slice[j] < p
 | |
| 			swap(slice, i, j)
 | |
| 			i++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	swap(slice, i, highIndex)
 | |
| 
 | |
| 	return i
 | |
| }
 | |
| 
 | |
| // HeapSort applys the heap sort algorithm to sort the collection, will change the original collection data.
 | |
| // Play: https://go.dev/play/p/u6Iwa1VZS_f
 | |
| func HeapSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	size := len(slice)
 | |
| 
 | |
| 	for i := size/2 - 1; i >= 0; i-- {
 | |
| 		sift(slice, i, size-1, comparator)
 | |
| 	}
 | |
| 	for j := size - 1; j > 0; j-- {
 | |
| 		swap(slice, 0, j)
 | |
| 		sift(slice, 0, j-1, comparator)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func sift[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
 | |
| 	i := lowIndex
 | |
| 	j := 2*i + 1
 | |
| 
 | |
| 	temp := slice[i]
 | |
| 	for j <= highIndex {
 | |
| 		if j < highIndex && comparator.Compare(slice[j], slice[j+1]) == -1 { //slice[j] < slice[j+1]
 | |
| 			j++
 | |
| 		}
 | |
| 		if comparator.Compare(temp, slice[j]) == -1 { //tmp < slice[j]
 | |
| 			slice[i] = slice[j]
 | |
| 			i = j
 | |
| 			j = 2*i + 1
 | |
| 		} else {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	slice[i] = temp
 | |
| }
 | |
| 
 | |
| // MergeSort applys the merge sort algorithm to sort the collection, will change the original collection data.
 | |
| // Play: https://go.dev/play/p/ydinn9YzUJn
 | |
| func MergeSort[T any](slice []T, comparator constraints.Comparator) {
 | |
| 	mergeSort(slice, 0, len(slice)-1, comparator)
 | |
| }
 | |
| 
 | |
| func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
 | |
| 	if lowIndex < highIndex {
 | |
| 		mid := (lowIndex + highIndex) / 2
 | |
| 		mergeSort(slice, lowIndex, mid, comparator)
 | |
| 		mergeSort(slice, mid+1, highIndex, comparator)
 | |
| 		merge(slice, lowIndex, mid, highIndex, comparator)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator constraints.Comparator) {
 | |
| 	i := lowIndex
 | |
| 	j := midIndex + 1
 | |
| 	temp := []T{}
 | |
| 
 | |
| 	for i <= midIndex && j <= highIndex {
 | |
| 		//slice[i] < slice[j]
 | |
| 		if comparator.Compare(slice[i], slice[j]) == -1 {
 | |
| 			temp = append(temp, slice[i])
 | |
| 			i++
 | |
| 		} else {
 | |
| 			temp = append(temp, slice[j])
 | |
| 			j++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if i <= midIndex {
 | |
| 		temp = append(temp, slice[i:midIndex+1]...)
 | |
| 	} else {
 | |
| 		temp = append(temp, slice[j:highIndex+1]...)
 | |
| 	}
 | |
| 
 | |
| 	for k := 0; k < len(temp); k++ {
 | |
| 		slice[lowIndex+k] = temp[k]
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // CountSort applys the count sort algorithm to sort the collection, don't change the original collection data.
 | |
| // Play: https://go.dev/play/p/tB-Umgm0DrP
 | |
| func CountSort[T any](slice []T, comparator constraints.Comparator) []T {
 | |
| 	size := len(slice)
 | |
| 	out := make([]T, size)
 | |
| 
 | |
| 	for i := 0; i < size; i++ {
 | |
| 		count := 0
 | |
| 		for j := 0; j < size; j++ {
 | |
| 			//slice[i] > slice[j]
 | |
| 			if comparator.Compare(slice[i], slice[j]) == 1 {
 | |
| 				count++
 | |
| 			}
 | |
| 		}
 | |
| 		out[count] = slice[i]
 | |
| 	}
 | |
| 
 | |
| 	return out
 | |
| }
 | |
| 
 | |
| // swap two slice value at index i and j
 | |
| func swap[T any](slice []T, i, j int) {
 | |
| 	slice[i], slice[j] = slice[j], slice[i]
 | |
| }
 | 
