排序

 

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)
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值