From ff4a4b2023cc3bf8af1e8b7581cadba2d7210305 Mon Sep 17 00:00:00 2001 From: Sebastian Steger Date: Wed, 20 Aug 2025 11:36:36 +0000 Subject: [PATCH] merge sort --- go/05-concurrency/mergeSort.go | 105 ++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/go/05-concurrency/mergeSort.go b/go/05-concurrency/mergeSort.go index 4160246..53e2ebd 100644 --- a/go/05-concurrency/mergeSort.go +++ b/go/05-concurrency/mergeSort.go @@ -4,9 +4,108 @@ 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 @@ -45,7 +144,7 @@ func merge(left, right []float64) []float64 { func main() { //1. DATA CREATION - data := make([]float64, 1000*1000*20) + data := make([]float64, 1000*1000*20) //*1000*20) for i := range data { data[i] = rand.Float64() * 100 // Random floats between 0 and 100 @@ -58,7 +157,9 @@ func main() { //2. SORTING start := time.Now() - mergeSortSequential(data) + //mergeSortSequential(data) + //mergeSortParallel(data) + mergeSortChannels(data) elapsed := time.Since(start) fmt.Printf("MergeSort took %s\n", elapsed)