1.快排(不稳定,平均O(nlgn),最坏O(n^2))
package main
import "fmt"
/*递归实现*/
func QuickSort(nums []int, begin int , end int){
if begin>=end {
return
}
index := Partition(nums,begin,end)
QuickSort(nums,begin,index-1)
QuickSort(nums,index+1,end)
}
/*非递归实现*/
func QuickSort(nums []int, begin int , end int){
if begin>=end {
return
}
begins := make([]int,0)
ends := make([]int,0)
begins = append(begins, begin)
ends = append(ends, end)
for len(begins)!=0 && len(ends)!=0 {
beginning := begins[0]
ending := ends[0]
begins = begins[1:]
ends = ends[1:]
if beginning>=ending {
continue
}
index := Partition(nums,beginning,ending)
begins = append(begins, beginning)
ends = append(ends, index-1)
begins = append(begins, index+1)
ends = append(ends, ending)
}
}
func Partition(nums []int, begin int, end int) int{
j := begin-1
for i:= begin;i<=end;i++ {
if nums[i] < nums[end] {
j++
nums[i], nums[j] = nums[j], nums[i]
}
}
j++
nums[j],nums[end] = nums[end],nums[j]
return j
}
func main () {
nums := []int{23,53,23,7,2,999,46,4}
fmt.Println(nums)
QuickSort(nums, 0, len(nums)-1)
fmt.Println(nums)
}
并发快排:数组非常大时有效(来源https://zhuanlan.zhihu.com/p/47383158)
每次我们都是开了两个Goroutine,而快排是随着递归调用越深,每次递归处理的数组元素越少,反而调用的递归次数越多,因此花费了大量的资源创建和调用Goroutine,反而原始的递归调用方法能把更多的资源都用到了计算上。因此我们稍作一些优化,在每次CoQuickSort调用的时候,判断左右边界的差如果小于一个数值,则直接调用QuickSort,不再继续并发创建Goroutine.
package main
import (
"fmt"
"math/rand"
"time"
)
//返回numRand个元素组成的切片,切片中每个元素值在[0,100)
func getTestSlice(numRand int) []int {
rand.Seed(time.Now().UnixNano())
nums := make([]int, numRand)
for i := 0; i < numRand; i++ {
nums[i] = rand.Intn(100)
}
return nums
}
//Partition不变
func Partiton(nums []int, begin int, end int) int {
j := begin-1
for i:= begin;i<=end;i++ {
if nums[i] < nums[end] {
j++
nums[i], nums[j] = nums[j], nums[i]
}
}
j++
nums[j],nums[end] = nums[end],nums[j]
return j
}
func CoQuickSort(nums []int, begin int, end int, finish chan int) {
if end <= begin {
finish <- 0
return
}
index := Partiton(nums, begin, end)
chanReceive := make(chan int)
defer close(chanReceive)
go CoQuickSort(nums, begin, index-1, chanReceive)
go CoQuickSort(nums, index+1, end, chanReceive)
<-chanReceive
<-chanReceive
finish <- 0
return
}
func main () {
nums := getTestSlice(10)
fmt.Println(nums)
finish := make(chan int)
defer close(finish)
go CoQuickSort(nums, 0, len(nums)-1, finish)
<-finish
fmt.Println(nums)
}
二路快排
#include <iostream>
using namespace std;
/*
https://blog.csdn.net/k_koris/article/details/80585979
1th:
partiron:0 9, target:24, mid:2
0 1 2 3 4 5 6 7 8 9
24 (53) 21 46 79 32 [15] 38 40 39
24 15 [21] (46) 79 32 53 38 40 39
21 15 24 46 79 32 53 38 40 39
2th-l:
partiron:0 1, target:21, mid:1
0 1 2 3 4 5 6 7 8 9
21 [15] (24) 46 79 32 53 38 40 39
15 21 24 46 79 32 53 38 40 39
2th-r:
partiron:3 9, target:46, mid:7
0 1 2 3 4 5 6 7 8 9
15 21 24 46 (79) 32 53 38 40 [39]
15 21 24 46 39 32 (53) 38 [40] 79
15 21 24 46 39 32 40 [38] (53) 79
15 21 24 38 39 32 40 46 53 79
3th-l(2th-r)
partiron:3 6, target:38, mid:7
0 1 2 3 4 5 6 7 8 9
15 21 24 38 (39) [32] 40 46 53 79
15 21 24 38 [32] (39) 40 46 53 79
15 21 24 32 38 39 40 46 53 79
3th-r(2th-r)
partiron:8 9, target:53, mid:7
0 1 2 3 4 5 6 7 8 9
15 21 24 32 38 39 40 46 53 [(79)]
15 21 24 32 38 39 40 46 [53] 79 ()
15 21 24 32 38 39 40 46 53 79
*/
void printArray(int p[]) {
for (int i=0; i<10; i++) {
cout << p[i] << " ";
}
cout << endl;
}
int partition(int p[],int left,int right) {
cout<<"partiron:"<<left<<" "<<right<<endl;
int key = p[left];
int i=left, j=right+1;
while(i <= j)
{
do{i++;} while(i <= right && p[i] < key);
do{j--;} while(p[j] > key);
if(i > j)
{
break;
}
swap(p[i], p[j]);
cout<<i<<" "<<j<<endl;
printArray(p);
}
swap(p[left], p[j]);
cout<<"mid: "<<j<<endl;
printArray(p);
return j;
}
void quickSort2(int p[],int left,int right){
if(left>=right){ return;}
int mid=partition(p,left,right);
quickSort2(p,left,mid-1);
quickSort2(p,mid+1,right);
}
int main() {
int arr[10] = {24,53,21,46,79,32,15,38,40,39};
cout << "init array:" <<endl;
printArray(arr);
quickSort2(arr,0,9);
cout << "sorted array:" <<endl;
printArray(arr);
return 0;
}
2.堆排序(不稳定,平均O(nlgn),最坏O(nlgn))
package main
import "fmt"
func heap(nums []int, begin int, end int) {
father := begin
child := 2*father + 1
for child < end-1 {
if child<end && nums[child+1] > nums[child] {
child++
}
if nums[child] <= nums[father] {
break
}
nums[child], nums[father] = nums[father], nums[child]
father = child
child = 2*father + 1
}
}
func HeapSort(nums []int) {
end := len(nums) - 1
for i:=len(nums)/2-1 ; i>=0; i--{
heap(nums,i,end)
}
for i:=end;i>0;i--{
nums[0], nums[i] = nums[i], nums[0]
heap(nums,0,i-1)
}
}
func main () {
nums := []int{23,53,23,7,2,999,46,4}
fmt.Println(nums)
HeapSort(nums)
fmt.Println(nums)
}
3.归并排序(稳定,平均O(nlgn),最坏O(nlgn))
package main
import "fmt"
func MergeSort(nums []int, sortNums []int, begin int , end int){
if begin>=end {
return
}
mid := (begin + end)>>1
MergeSort(nums, sortNums, begin, mid)
MergeSort(nums, sortNums, mid+1, end)
i := begin
j := mid+1
index := begin
for i<=mid || j<=end{
if j>end || (i<=mid && nums[i]<nums[j]){
sortNums[index] = nums[i]
i++
} else {
sortNums[index] = nums[j]
j++
}
index++
}
for i:=begin;i<=end;i++ {
nums[i]=sortNums[i]
}
}
func main () {
nums := []int{23,53,23,7,2,999,46,4}
sortNums := make([]int, len(nums))
MergeSort(nums, sortNums, 0, len(nums)-1)
fmt.Println(sortNums)
}
并发归并排序
package main
import "fmt"
func Merge(nums []int, sortNums []int, begin int, end int, mid int) {
i := begin
j := mid+1
index := begin
for i<=mid || j<=end{
if j>end || (i<=mid && nums[i]<nums[j]){
sortNums[index] = nums[i]
i++
} else {
sortNums[index] = nums[j]
j++
}
index++
}
for i:=begin;i<=end;i++ {
nums[i]=sortNums[i]
}
}
func MergeSort(nums []int, sortNums []int, begin int , end int, ch chan int){
if begin >= end {
ch<-0
return
}
mid := (begin + end)>>1
chReceive := make(chan int)
defer close(chReceive)
go MergeSort(nums, sortNums, begin, mid, chReceive)
go MergeSort(nums, sortNums, mid+1, end, chReceive)
<-chReceive
<-chReceive
Merge(nums, sortNums, begin, end, mid)
ch<-0
}
func main () {
nums := []int{23,53,23,7,2,999,46,4}
sortNums := make([]int, len(nums))
ch := make(chan int)
defer close(ch)
go MergeSort(nums, sortNums, 0, len(nums)-1, ch)
<-ch
fmt.Println(sortNums)
}
4.三种O(n^2)排序
选择(不稳定,平均O(n^2),最坏O(n^2))
插入(稳定,平均O(n^2),最坏O(n^2))
冒泡(稳定,平均O(n^2),最坏O(n^2))
package main
import "fmt"
func SelectSort(nums []int) {
for i:=0; i<len(nums); i++ {
target := nums[i]
index := i
for j:=i+1; j<len(nums); j++ {
if nums[j]<target{
target = nums[j]
index = j
}
}
nums[i], nums[index] = nums[index], nums[i]
}
}
func BubbleSort(nums []int) {
for i:=0; i<len(nums)-1; i++ {
for j:=0; j<len(nums)-i-1; j++ {
if nums[j+1] < nums[j] {
nums[j], nums[j+1] = nums[j+1], nums[j]
}
}
}
}
func InsertSort(nums []int) {
for i:=1;i<len(nums);i++ {
target := nums[i]
j := i-1
for j>=0 && nums[j]>target {
nums[j+1] = nums[j]
j--
}
nums[j+1] = target
}
}
func main () {
nums := []int{23,53,23,7,2,999,46,4}
fmt.Println(nums)
SelectSort(nums)
BubbleSort(nums)
InsertSort(nums)
fmt.Println(nums)
}
5.基数排序(不稳定,平均O(d(n+r)),最坏O(d(n+r)))
d数据长度,r桶的个数(十进制数一般用10个桶)
package main
import "fmt"
//数组中最长数字的十进制位个数
func maxBit(nums []int) int{
bit := 1
nextBitMinNum := 10
for _,v := range nums {
for v >= nextBitMinNum {
nextBitMinNum *= 10
bit++
}
}
return bit
}
//从低位开始的基数排序
func RadixSort(nums []int){
bit := maxBit(nums)
tmp := make([]int,len(nums))
bucket := make([]int,10)
radix := 1
for i:=0; i<bit; i++ {
//每轮开始时桶中元素个数为0
var k int
for j:=0; j<10; j++ {
bucket[j] = 0
}
//统计每个桶中的记录数
for j:=0; j<len(nums); j++ {
k = (nums[j] / radix) % 10;
bucket[k]++;
}
//桶中的最大元素的在所有桶合并后的序号,index=序号-1
for j:=1; j<10; j++ {
bucket[j] = bucket[j-1] + bucket[j];
}
//将所有桶中记录依次收集到tmp中
for j:=len(nums)-1; j>=0; j-- {
k = (nums[j] / radix) % 10;
tmp[bucket[k] - 1] = nums[j];
bucket[k]--;
}
//将临时数组的内容复制到nums中
for j:=0; j<len(nums); j++ {
nums[j] = tmp[j];
}
radix = radix * 10
}
}
func main () {
nums := []int{23,53,23,7,2,999,46,4}
fmt.Println(nums)
RadixSort(nums)
fmt.Println(nums)
}