1
0
mirror of https://gitlab.com/Anson-Projects/anson-stuff/Go-v-Rust-Quicksort.git synced 2025-06-16 06:06:40 +00:00

both works

This commit is contained in:
Anson Biggs 2022-04-25 17:44:42 -07:00
parent f7f91c2da5
commit 934f5aa61b
2 changed files with 93 additions and 93 deletions

View File

@ -2,117 +2,117 @@ package main
import ( import (
"fmt" "fmt"
"io"
"math/rand" "math/rand"
"os"
"time" "time"
) )
func Cqsort(s []int, MAXGOROUTINES int) { func quicksort(slice []int) {
if len(s) <= 1 {
if len(slice) <= 1 {
return return
} }
workers := make(chan int, MAXGOROUTINES-1)
for i := 0; i < (MAXGOROUTINES - 1); i++ { pivot := partition(slice, choose_pivot(slice))
workers <- 1 left := slice[0:pivot]
} right := slice[pivot+1:]
cqsort(s, nil, workers)
quicksort(left)
quicksort(right)
} }
func cqsort(s []int, done chan int, workers chan int) { func par_quicksort(slice []int) {
// report to caller that we're finished
if done != nil {
defer func() { done <- 1 }()
}
if len(s) <= 1 { if len(slice) <= 1 {
return return
} }
// since we may use the doneChannel synchronously
// we need to buffer it so the synchronous code will
// continue executing and not block waiting for a read
doneChannel := make(chan int, 1)
pivotIdx := partition(s) pivot := partition(slice, choose_pivot(slice))
left := slice[0:pivot]
right := slice[pivot+1:]
select { go quicksort(left)
case <-workers: go quicksort(right)
// if we have spare workers, use a goroutine
// for parallelization
go cqsort(s[:pivotIdx+1], doneChannel, workers)
default:
// if no spare workers, sort synchronously
cqsort(s[:pivotIdx+1], nil, workers)
// calling this here as opposed to using the defer
doneChannel <- 1
}
// use the existing goroutine to sort above the pivot
cqsort(s[pivotIdx+1:], nil, workers)
// if we used a goroutine we'll need to wait for
// the async signal on this channel, if not there
// will already be a value in the channel and it shouldn't block
<-doneChannel
return
} }
func partition(s []int) (swapIdx int) { func partition(slice []int, pivot int) int {
pivotIdx, pivot := pickPivot(s) if len(slice) == 1 {
// swap right-most element and pivot return 0
s[len(s)-1], s[pivotIdx] = s[pivotIdx], s[len(s)-1] }
// sort elements keeping track of pivot's idx
for i := 0; i < len(s)-1; i++ { mid := len(slice) - 1
if s[i] < pivot { swap(slice, pivot, mid)
s[i], s[swapIdx] = s[swapIdx], s[i] left := 0
swapIdx++ right := mid - 1
for left < right {
if slice[left] <= slice[mid] {
left = left + 1
} else if slice[right] >= slice[mid] {
right = right - 1
} else {
swap(slice, left, right)
left = left + 1
right = right + 1
} }
} }
// swap pivot back to its place and return
s[swapIdx], s[len(s)-1] = s[len(s)-1], s[swapIdx] if left > right {
return swap(slice, left, mid)
return left
}
if slice[left] >= slice[mid] {
swap(slice, left, mid)
return left
} else if slice[left] <= slice[mid] {
swap(slice, left+1, mid)
return left + 1
}
panic("partition falied.")
} }
func pickPivot(s []int) (pivotIdx int, pivot int) { func choose_pivot(slice []int) int {
pivotIdx = rand.Intn(len(s)) left := 0
pivot = s[pivotIdx] mid := len(slice) / 2
return right := len(slice) - 1
if slice[right] < slice[left] {
left, right = right, left
}
if slice[mid] <= slice[left] {
return left
} else if slice[right] <= slice[mid] {
return right
} else {
return mid
}
}
func swap(slice []int, a int, b int) {
if a <= len(slice) && b <= len(slice) {
slice[a], slice[b] = slice[b], slice[a]
}
} }
func main() { func main() {
file, err := os.Open("data/perm50e6.txt") sortSize := 20000000
if err != nil { // MAXGOROUTINES := 1
fmt.Println(err) unsorted := make([]int, 0, sortSize)
os.Exit(1) unsorted = rand.Perm(sortSize)
}
var perline int
var nums1 []int
var nums2 []int
fmt.Println("Reading File:...")
for {
_, err := fmt.Fscanf(file, "%d\n", &perline) // give a patter to scan
if err != nil {
if err == io.EOF {
break // stop reading the file
}
fmt.Println(err)
os.Exit(1)
}
nums1 = append(nums1, perline)
nums2 = append(nums2, perline)
}
fmt.Println("Sorting!")
start := time.Now() start := time.Now()
Cqsort(nums1, 16) quicksort(unsorted)
duration := time.Since(start) duration := time.Since(start)
fmt.Println("single ", duration)
fmt.Println("goroutines", duration) unsorted = rand.Perm(sortSize)
start = time.Now() start = time.Now()
Cqsort(nums2, 1) par_quicksort(unsorted)
duration = time.Since(start) duration = time.Since(start)
fmt.Println(duration) fmt.Println(duration)

View File

@ -17,14 +17,14 @@ fn choose_pivot<T: Ord>(slice: &[T]) -> usize {
} }
fn partition<T: Ord>(slice: &mut [T], pivot: usize) -> usize { fn partition<T: Ord>(slice: &mut [T], pivot: usize) -> usize {
let mxix = slice.len() - 1; let mid = slice.len() - 1;
slice.swap(pivot, mxix); slice.swap(pivot, mid);
let (mut left, mut right) = (0, mxix - 1); let (mut left, mut right) = (0, mid - 1);
while left < right { while left < right {
if slice[left] <= slice[mxix] { if slice[left] <= slice[mid] {
left += 1; left += 1;
} else if slice[right] >= slice[mxix] { } else if slice[right] >= slice[mid] {
right -= 1; right -= 1;
} else { } else {
slice.swap(left, right); slice.swap(left, right);
@ -35,16 +35,16 @@ fn partition<T: Ord>(slice: &mut [T], pivot: usize) -> usize {
if left > right { if left > right {
// We just swapped the final two. // We just swapped the final two.
slice.swap(left, mxix); slice.swap(left, mid);
return left; return left;
} }
// Left and right met. // Left and right met.
if slice[left] >= slice[mxix] { if slice[left] >= slice[mid] {
slice.swap(left, mxix); slice.swap(left, mid);
return left; return left;
} else if slice[left] <= slice[mxix] { } else if slice[left] <= slice[mid] {
slice.swap(left + 1, mxix); slice.swap(left + 1, mid);
return left + 1; return left + 1;
} }