用go语言写的快速排序
因为工作原因接触了go语言,由于其特性,并行编程非常方便。而go语言特有的入门级的特性最主要的就包括了用go开协程,用channel进行同步。
用这些入门级特性写了一个多线程版本的快速排序是一个非常好的练习。
package main
import (
"fmt"
"sync"
)
var (
workerNum = 4
)
type task struct {
start, end int
}
func newTask(start, end int) *task {
return &task{
start: start,
end: end,
}
}
func swap(arr []int, i, j int) {
t := arr[i]
arr[i] = arr[j]
arr[j] = t
}
func partition(arr []int, start, end int) int {
slow := start
for i := start; i < end; i++ {
if arr[i] < arr[end] {
swap(arr, i, slow)
slow++
}
}
swap(arr, slow, end)
return slow
}
func worker(w int, ch chan *task, arr []int, wg *sync.WaitGroup) {
for {
select {
case t, ok := <-ch:
if !ok {
return
}
m := partition(arr, t.start, t.end)
fmt.Printf("worker %v working on (%v,%v,%v)\n", w, t.start, t.end, m)
wg.Done()
go func() {
if t.start < m {
ch <- newTask(t.start, m-1)
}
if m < t.end {
ch <- newTask(m+1, t.end)
}
}()
}
}
}
func sort(arr []int) {
ch := make(chan *task, 5)
var wg sync.WaitGroup
wg.Add(len(arr))
for i := 0; i < workerNum; i++ {
go worker(i, ch, arr, &wg)
}
// put the first task into channel
ch <- newTask(0, len(arr)-1)
wg.Wait()
close(ch)
}
func main() {
arr := []int{9, 2, 7, 4, 5, 6, 3, 8, 1}
sort(arr)
fmt.Println(arr)
}