package main import ( "fmt" "math/rand" "sort" "sync" "time" ) func mergeSortChannelsInternal(data []float64, sorted chan<- float64) { defer close(sorted) if len(data) <= 10000 { sortedData := make([]float64, len(data)) copy(sortedData, data) mergeSortSequential(sortedData) for _, x := range sortedData { sorted <- x } } else { mid := len(data) / 2 left := data[:mid] right := data[mid:] sortedLeft := make(chan float64, 1000) sortedRight := make(chan float64, 1000) go mergeSortChannelsInternal(left, sortedLeft) go mergeSortChannelsInternal(right, sortedRight) mergeChannels(sortedLeft, sortedRight, sorted) } } func mergeChannels(a, b <-chan float64, out chan<- float64) { var okA, okB bool var valA, valB float64 for { if !okA { valA, okA = <-a } if !okB { valB, okB = <-b } if !okA && !okB { break } if !okA { out <- valB okB = false continue } if !okB { out <- valA okA = false continue } if valA < valB { out <- valA okA = false } else { out <- valB okB = false } } } func mergeSortChannels(data []float64) { sorted := make(chan float64, 1000) go mergeSortChannelsInternal(data, sorted) sortedData := make([]float64, len(data)) i := 0 for x := range sorted { sortedData[i] = x i++ } copy(data, sortedData) } func mergeSortParallel(data []float64) { if len(data) <= 10000 { mergeSortSequential(data) return } mid := len(data) / 2 left := data[:mid] right := data[mid:] var wg sync.WaitGroup wg.Add(2) go func() { mergeSortParallel(left); wg.Done() }() go func() { mergeSortParallel(right); wg.Done() }() wg.Wait() copy(data, merge(left, right)) } func mergeSortSequential(data []float64) { if len(data) <= 1 { return } mid := len(data) / 2 left := data[:mid] right := data[mid:] mergeSortSequential(left) mergeSortSequential(right) copy(data, merge(left, right)) } func merge(left, right []float64) []float64 { result := make([]float64, 0, len(left)+len(right)) i, j := 0, 0 for i < len(left) && j < len(right) { if left[i] < right[j] { result = append(result, left[i]) i++ } else { result = append(result, right[j]) j++ } } result = append(result, left[i:]...) result = append(result, right[j:]...) return result } func main() { //1. DATA CREATION data := make([]float64, 1000*1000*20) //*1000*20) for i := range data { data[i] = rand.Float64() * 100 // Random floats between 0 and 100 } expected := make([]float64, len(data)) copy(expected, data) sort.Float64s(expected) //2. SORTING start := time.Now() //mergeSortSequential(data) //mergeSortParallel(data) mergeSortChannels(data) elapsed := time.Since(start) fmt.Printf("MergeSort took %s\n", elapsed) //3. VERIFICATION if sort.Float64sAreSorted(data) { fmt.Println("Data is sorted correctly") } else { fmt.Println("Data is NOT sorted correctly") } if len(data) != len(expected) { fmt.Println("Data and expected slices have different lengths") return } for i := range data { if data[i] != expected[i] { fmt.Println("Data and expected slices do not match") return } } fmt.Println("Data and expected slices match") }