forked from steger/pr3-sose2026
188 lines
3.2 KiB
Go
188 lines
3.2 KiB
Go
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")
|
|
}
|