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:
parent
f7f91c2da5
commit
934f5aa61b
166
golang/main.go
166
golang/main.go
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user