294 lines
7.0 KiB
Go
294 lines
7.0 KiB
Go
|
package stream
|
|||
|
|
|||
|
import (
|
|||
|
"math"
|
|||
|
"runtime"
|
|||
|
)
|
|||
|
|
|||
|
/**
|
|||
|
* Reference:
|
|||
|
* http://www.cnblogs.com/gw811/archive/2012/10/04/2711746.html
|
|||
|
*/
|
|||
|
|
|||
|
// Comparator 比较器
|
|||
|
type Comparator struct {
|
|||
|
CompareTo func(interface{}, interface{}) int
|
|||
|
}
|
|||
|
|
|||
|
// Sorted 对数据流操作,升序排序
|
|||
|
func (s *Stream) Sorted(comparator *Comparator) *Stream {
|
|||
|
return s.MSorted(comparator)
|
|||
|
}
|
|||
|
|
|||
|
// QSorted 对数据流操作,快排,升序排序
|
|||
|
func (s *Stream) QSorted(comparator *Comparator) *Stream {
|
|||
|
qsort(s.list, 0, len(s.list), comparator.CompareTo)
|
|||
|
s.isParallel = false
|
|||
|
return s
|
|||
|
}
|
|||
|
|
|||
|
// MSorted 对数据流操作,归并排序,升序排序
|
|||
|
func (s *Stream) MSorted(comparator *Comparator) *Stream {
|
|||
|
aux := make([]interface{}, len(s.list)) //辅助切片
|
|||
|
var ch chan int
|
|||
|
cores := runtime.NumCPU()
|
|||
|
maxDepth := int(math.Log2(float64(cores)) + 1)
|
|||
|
if s.isParallel {
|
|||
|
ch = make(chan int)
|
|||
|
for j := 0; j < cores; j++ {
|
|||
|
go func(idx int) {
|
|||
|
for i := idx; i < len(s.list); i += cores {
|
|||
|
aux[i] = s.list[i]
|
|||
|
}
|
|||
|
ch <- 0
|
|||
|
}(j)
|
|||
|
}
|
|||
|
waitCh(ch, cores)
|
|||
|
go mergeSort(aux, s.list, 0, len(s.list), 0, comparator.CompareTo, 0, maxDepth, ch)
|
|||
|
waitCh(ch, 1)
|
|||
|
} else {
|
|||
|
for i, v := range s.list {
|
|||
|
aux[i] = v
|
|||
|
}
|
|||
|
mergeSort(aux, s.list, 0, len(s.list), 0, comparator.CompareTo, 0, maxDepth, ch)
|
|||
|
}
|
|||
|
s.isParallel = false
|
|||
|
return s
|
|||
|
}
|
|||
|
func waitCh(ch chan int, num int) {
|
|||
|
if ch != nil {
|
|||
|
for i := 0; i < num; i++ {
|
|||
|
<-ch
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 对指定 int 型数组的指定范围按数字升序进行排序。
|
|||
|
*/
|
|||
|
func qsort(list []interface{}, fromIndex int, toIndex int, comp func(interface{}, interface{}) int) {
|
|||
|
qsort1(list, fromIndex, toIndex-fromIndex, comp)
|
|||
|
}
|
|||
|
|
|||
|
func qsort1(list []interface{}, off int, len int, comp func(interface{}, interface{}) int) {
|
|||
|
/*
|
|||
|
* 当待排序的数组中的元素个数小于 7 时,采用插入排序 。
|
|||
|
*
|
|||
|
* 尽管插入排序的时间复杂度为O(n^2),但是当数组元素较少时, 插入排序优于快速排序,因为这时快速排序的递归操作影响性能。
|
|||
|
*/
|
|||
|
if len < 7 {
|
|||
|
for i := off; i < len+off; i++ {
|
|||
|
for j := i; j > off && comp(list[j-1], list[j]) > 0; j-- {
|
|||
|
swap(list, j, j-1)
|
|||
|
}
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
/*
|
|||
|
* 当待排序的数组中的元素个数大于 或等于7 时,采用快速排序 。
|
|||
|
*
|
|||
|
* Choose a partition element, v
|
|||
|
* 选取一个划分元,V
|
|||
|
*
|
|||
|
* 较好的选择了划分元(基准元素)。能够将数组分成大致两个相等的部分,避免出现最坏的情况。例如当数组有序的的情况下,
|
|||
|
* 选择第一个元素作为划分元,将使得算法的时间复杂度达到O(n^2).
|
|||
|
*/
|
|||
|
// 当数组大小为size=7时 ,取数组中间元素作为划分元。
|
|||
|
m := off + (len >> 1)
|
|||
|
// 当数组大小 7<size<=40时,取首、中、末 三个元素中间大小的元素作为划分元。
|
|||
|
if len > 7 {
|
|||
|
l := off
|
|||
|
n := off + len - 1
|
|||
|
/*
|
|||
|
* 当数组大小 size>40 时 ,从待排数组中较均匀的选择9个元素,
|
|||
|
* 选出一个伪中数做为划分元。
|
|||
|
*/
|
|||
|
if len > 40 {
|
|||
|
s := len / 8
|
|||
|
l = med3(list, l, l+s, l+2*s, comp)
|
|||
|
m = med3(list, m-s, m, m+s, comp)
|
|||
|
n = med3(list, n-2*s, n-s, n, comp)
|
|||
|
}
|
|||
|
// 取出中间大小的元素的位置。
|
|||
|
m = med3(list, l, m, n, comp) // Mid-size, med of 3
|
|||
|
}
|
|||
|
|
|||
|
//得到划分元V
|
|||
|
v := list[m]
|
|||
|
|
|||
|
// Establish Invariant: v* (<v)* (>v)* v*
|
|||
|
a := off
|
|||
|
b := a
|
|||
|
c := off + len - 1
|
|||
|
d := c
|
|||
|
for true {
|
|||
|
for b <= c && comp(list[b], v) <= 0 {
|
|||
|
if list[b] == v {
|
|||
|
swap(list, a, b)
|
|||
|
a++
|
|||
|
}
|
|||
|
b++
|
|||
|
}
|
|||
|
for c >= b && comp(list[c], v) >= 0 {
|
|||
|
if comp(list[c], v) == 0 {
|
|||
|
swap(list, c, d)
|
|||
|
d--
|
|||
|
}
|
|||
|
c--
|
|||
|
}
|
|||
|
if b > c {
|
|||
|
break
|
|||
|
}
|
|||
|
swap(list, b, c)
|
|||
|
b++
|
|||
|
c--
|
|||
|
}
|
|||
|
// Swap partition elements back to middle
|
|||
|
s := off + len
|
|||
|
n := s
|
|||
|
s = min(a-off, b-a)
|
|||
|
vecswap(list, off, b-s, s)
|
|||
|
s = min(d-c, n-d-1)
|
|||
|
vecswap(list, b, n-s, s)
|
|||
|
// Recursively sort non-partition-elements
|
|||
|
s = b - a
|
|||
|
if s > 1 {
|
|||
|
qsort1(list, off, s, comp)
|
|||
|
}
|
|||
|
s = d - c
|
|||
|
if s > 1 {
|
|||
|
qsort1(list, n-s, s, comp)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func min(a int, b int) int {
|
|||
|
if a >= b {
|
|||
|
return b
|
|||
|
}
|
|||
|
return a
|
|||
|
}
|
|||
|
|
|||
|
func max(a int, b int) int {
|
|||
|
if a < b {
|
|||
|
return b
|
|||
|
}
|
|||
|
return a
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Swaps x[a] with x[b].
|
|||
|
*/
|
|||
|
func swap(list []interface{}, a int, b int) {
|
|||
|
list[a], list[b] = list[b], list[a]
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
|
|||
|
*/
|
|||
|
func vecswap(list []interface{}, a int, b int, n int) {
|
|||
|
for i := 0; i < n; i++ {
|
|||
|
swap(list, a, b)
|
|||
|
a++
|
|||
|
b++
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns the index of the median of the three indexed integers.
|
|||
|
*/
|
|||
|
func med3(list []interface{}, a int, b int, c int, comp func(interface{}, interface{}) int) int {
|
|||
|
if comp(list[a], list[b]) < 0 {
|
|||
|
if comp(list[b], list[c]) < 0 {
|
|||
|
return b
|
|||
|
}
|
|||
|
if comp(list[a], list[c]) < 0 {
|
|||
|
return c
|
|||
|
}
|
|||
|
return a
|
|||
|
}
|
|||
|
if comp(list[b], list[c]) > 0 {
|
|||
|
return b
|
|||
|
}
|
|||
|
if comp(list[a], list[c]) > 0 {
|
|||
|
return c
|
|||
|
}
|
|||
|
return a
|
|||
|
}
|
|||
|
|
|||
|
func rangeCopy(src []interface{}, low int, dest []interface{}, destLow int, length int) {
|
|||
|
for i := 0; i < length; i++ {
|
|||
|
dest[destLow+i] = src[low+i]
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Src is the source array that starts at index 0
|
|||
|
* Dest is the (possibly larger) array destination with a possible offset
|
|||
|
* low is the index in dest to start sorting
|
|||
|
* high is the end index in dest to end sorting
|
|||
|
* off is the offset to generate corresponding low, high in src
|
|||
|
*/
|
|||
|
func mergeSort(src []interface{}, dest []interface{}, low int, high int, off int, comp func(interface{}, interface{}) int, depth int, maxDepth int, ch chan int) {
|
|||
|
defer func() {
|
|||
|
if ch != nil {
|
|||
|
ch <- 0
|
|||
|
}
|
|||
|
}()
|
|||
|
length := high - low
|
|||
|
|
|||
|
// Insertion sort on smallest arrays
|
|||
|
if length < 7 {
|
|||
|
for i := low; i < high; i++ {
|
|||
|
for j := i; j > low && comp(dest[j-1], dest[j]) > 0; j-- {
|
|||
|
swap(dest, j, j-1)
|
|||
|
}
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Recursively sort halves of dest into src
|
|||
|
destLow := low
|
|||
|
destHigh := high
|
|||
|
low += off
|
|||
|
high += off
|
|||
|
/*
|
|||
|
* >>>:无符号右移运算符
|
|||
|
* expression1 >>> expresion2:expression1的各个位向右移expression2
|
|||
|
* 指定的位数。右移后左边空出的位数用0来填充。移出右边的位被丢弃。
|
|||
|
* 例如:-14>>>2; 结果为:1073741820
|
|||
|
*/
|
|||
|
mid := (low + high) >> 1
|
|||
|
if ch != nil {
|
|||
|
if depth < maxDepth {
|
|||
|
ch2 := make(chan int)
|
|||
|
go mergeSort(dest, src, low, mid, -off, comp, depth+1, maxDepth, ch2)
|
|||
|
go mergeSort(dest, src, mid, high, -off, comp, depth+1, maxDepth, ch2)
|
|||
|
waitCh(ch2, 2)
|
|||
|
} else {
|
|||
|
mergeSort(dest, src, low, mid, -off, comp, depth+1, maxDepth, nil)
|
|||
|
mergeSort(dest, src, mid, high, -off, comp, depth+1, maxDepth, nil)
|
|||
|
}
|
|||
|
} else {
|
|||
|
mergeSort(dest, src, low, mid, -off, comp, depth+1, maxDepth, ch)
|
|||
|
mergeSort(dest, src, mid, high, -off, comp, depth+1, maxDepth, ch)
|
|||
|
}
|
|||
|
|
|||
|
// If list is already sorted, just copy from src to dest. This is an
|
|||
|
// optimization that results in faster sorts for nearly ordered lists.
|
|||
|
if comp(src[mid-1], src[mid]) <= 0 {
|
|||
|
rangeCopy(src, low, dest, destLow, length)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// Merge sorted halves (now in src) into dest
|
|||
|
for i, p, q := destLow, low, mid; i < destHigh; i++ {
|
|||
|
if q >= high || p < mid && comp(src[p], src[q]) <= 0 {
|
|||
|
dest[i] = src[p]
|
|||
|
p++
|
|||
|
} else {
|
|||
|
dest[i] = src[q]
|
|||
|
q++
|
|||
|
}
|
|||
|
}
|
|||
|
}
|