八大基础排序算法总结(golang实现)

自己写的代码tm都不知道啥意思了,还是要定时复习啊

一、冒泡排序n^2

基本思想:对于升序来说,两层for循环,第一层表示需要冒多少次,第二层用于比较,两两比较,如果前数大于后数,交换,否则不交换

package main
import "fmt"
func Swap(arr []int, i, j int){
	arr[i],arr[j]=arr[j],arr[i]
}
func MaoPaoSort(arr []int){
	for i:=0;i<len(arr);i++{
		for j:=1;j<len(arr)-i;j++ {
			if arr[j]<arr[j-1] {
				Swap(arr, j,j-1)
			}
		}
	}
}
func main(){
	arr := []int{9,5,7,4,1,3,6,0,6,8}
	MaoPaoSort(arr)
	fmt.Println(arr)
}

二、快速排序nlogn

基本思想:选择一个基准,两个游标low,high,0-low全比基准小,high-len(arr)全比基准大,对0-low和high-len(arr)递归

package main

import (
	"fmt"
	"time"
	"math/rand"
)

//交换的函数
func Swap(arr []int, i, j int){
	arr[i],arr[j]=arr[j],arr[i]
}
func QuickSort2(arr []int, left,right int){
	if (right-left)<1{//递归结束标志,当数组只有一个时认为时有序的
		return
	}
	//以第一个作为基准(升序)
	posnum := arr[left]
	//定义区域
	low := left  //low需要++,最终使arr[left, low]都是小于基准
	high := right+1  //high-- 使arr[high, right]都是大于基准的
					 //可以将high := right,后面的代码相继就要改
	i := left+1   //i++使[low+1, i]都是等于基准的
	//开始移动,大的一后面,小的移前面,等的一中间
	for i<(high){//当i与 high+1重回结束循环
		if arr[i]>posnum{
			Swap(arr, i, high-1)
			high--
			
		}else if arr[i]<posnum{
			
			Swap(arr, i, low+1)
			i++
			low++
			//为什么>的时候不用i++呢:在小于的时候,交换过来的数已经做过了判断,
			// 已经是比基准小的数,而大于的时候, 交换的是后面的数,后面的数没有遍历到,
			//所以需要i不变,以便继续判断交换过来的数	
		}else{
			i++//等于则跳到下一个继续判断
		}
	}
	//不要忘了这一步,基准与low区间最后那个交换,要知道(left,low]都是比基准小的
	Swap(arr,left,low)
	//大小区域分别递归
	QuickSort2(arr, left, low-1)
	QuickSort2(arr, high, right)
	
}

func main(){
	//创建数组
	arr := make([]int, 20,20)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i:=0;i<20;i++{
		arr[i]=r.Intn(100)
	}
	fmt.Println("before sort",arr)
	QuickSort2(arr, 0, len(arr)-1)
	fmt.Println("after  sort",arr)

}

三、二分插入排序nlogn

基本思路:i从1开始到n结束,以0到i-1是有序序列,对arr[i],用二分查找,在0到i-1范围内查找对应位置,以升序为例,找到第一个比arr[i]稍大的。

 package main

import (
	"fmt"
	"time"
	"math/rand"
)

func MakeArr()[]int{
	var list []int
	re := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0;i<10;i++{
		list = append(list, re.Intn(1000))
	}
	return list
}

func BinaryFindPos(area []int, start, end, cur int)int{
	//结束标志,返回start与cur值较大的数
	if start == end{
		if area[start]>area[cur]{
			return start
		}else{
			return cur
		}
	}
	med := (start+end)/2
	//递归逼近该位置
	//找到比area[cur]稍稍大的数
	if area[med]<area[cur]{
		return BinaryFindPos(area, med+1, end, cur)
	}else {
		return BinaryFindPos(area, start, med, cur)
	}
}
func BinaryInsertSort(area []int)[]int{
	for  i:=1;i<len(area);i++{
		pos := BinaryFindPos(area, 0, i-1, i)
		fmt.Println("pos :",pos)
		if pos != i{
			//123 0
			for j:=i;j>pos;j--{
				area[j], area[j-1]=area[j-1],area[j]
			}
		}
	}
	return area
}
func main(){
	area := MakeArr()
	fmt.Println(area)
	area = BinaryInsertSort(area)
	fmt.Println(area)
}

四、希尔排序n^1.3

基本思路:以数组长度一半为步长,每次步长减半,循环步长次。其中每次循环都要分成步长组数据,每组数据是arr[i+步长],对每组数据进行冒泡排序,插入排序也可以

package main

import (
	"time"
	"fmt"
)

func ShellSort(arr []int)[]int{
	length := len(arr)
	if length<=1{
		return arr
	}
	stap := length/2
	for stap>0{
		for i:=0;i<stap;i++{
			ShellSortInsert(arr, i, stap)
		}
		stap/=2
	}
	time.Sleep(1*time.Second)
	return arr
}

func ShellSortInsert(arr []int ,start, stap int)[]int{
	length := len(arr)
	if length<=1{
		return arr
	}
	for i:=start+stap;i<length;i+=stap{
		tmp := arr[i]
		for j:=i-stap;j>=0;j-=stap{
			if arr[j]>tmp{
				arr[j+stap],arr[j]=arr[j],arr[j+stap]
			}
		}
	}
	return arr
}



func main(){
	arr:=[]int{1,9,2,8,3,7,6,4,5,112,102,1,9,2,8,3,7,6,4,5,112,102,1,9,2,8,3,7,6,4,5,112,102,1,9,2,8,3,7,6,4,5,112,102,1,9,2,8,3,7,6,4,5,112,102,1,9,2,8,3,7,6,4,5,112,102}
	start:=time.Now()
	ShellSort(arr)
	fmt.Println(time.Since(start))
	fmt.Println(arr)
}

5、选择排序n^2

基本思路:每次选择最小的(最大的)放到i的位置

package main

import (
	"fmt"
)

func SelectSort(arr []int)[]int{
	if len(arr)<=1{
		return arr
	}
	for i:=0;i<len(arr)-1;i++{
		min := i
		for j:=i+1;j<len(arr);j++{
			if arr[j]<arr[min]{
				min=j
			}
		}
		arr[min], arr[i]=arr[i],arr[min]
		fmt.Println(arr)
	}
	return arr
}

func main(){
	arr := []int{9,8,6,5,7,1,2,3,5}
	arr = SelectSort(arr)
	fmt.Println(arr)
}

6、堆排序nlogn

就是二叉树,保证每个子节点都小于父节点(对于升序来说),一共需要循环n次,每次维护一个最大堆,将arr[0]与二叉树最后一个节点交换,二叉树长度减一,循环进行。也就是利用最大堆循环的找出0到len-i最大值,与len-i交换

package main

import (
	"fmt"
)


func HeapSort(arr []int)[]int{
	if len(arr)<=1{
		return arr
	}
	length := len(arr)
	for i:=0;i<length-1;i++{
		lastlen := length-i
		BinaryTreeFindMax(arr, lastlen)
		arr[lastlen-1], arr[0]=arr[0],arr[lastlen-1]
		fmt.Println(arr)
	}
	return arr
}
func BinaryTreeFindMax(arr []int, length int){
	if length<=1{
		return
	}
	depth := length/2-1
	for i:=depth;i>=0;i--{
		max:=i
		leftchild := 2*i+1
		rightchild := 2*i+2
		if leftchild<=length-1&&arr[leftchild]>arr[max]{
			max=leftchild
		}
		if rightchild<=length-1&&arr[rightchild]>arr[max]{
			max=rightchild
		}
		if max != i{
			arr[max], arr[i]=arr[i],arr[max]
		}
	}
}
func main(){
	arr := []int{5,7,4,1,9,6,3,8,2}
	arr = HeapSort(arr)
	fmt.Println(arr)
}

7.基数排序d(r+n)

先以个位排序,再十位,再百位,以此类推。
也就是说个位是0的放一个桶里,1放一个桶里。。。。。。再把这是个桶连起来。
再十位的。。。。。。
这个算法很幼稚

package main
import "fmt"
func jishuSort(arr []int, base int)[]int{
	//base 是 得到对应位的帮助比如 123 得到个位123%10/1,得到十位123%100/10,得到百位数字123%1000/100
	if len(arr)<=1 {
		return arr
	}
	tong0:=make([]int,0)
	tong1:=make([]int,0)
	tong2:=make([]int,0)
	tong3:=make([]int,0)
	tong4:=make([]int,0)
	tong5:=make([]int,0)
	tong6:=make([]int,0)
	tong7:=make([]int,0)
	tong8:=make([]int,0)
	tong9:=make([]int,0)
	//首先需要知道有多少位,这里直接假设有最多三位
	for i :=0;i<len(arr);i++ {
		if arr[i]%base/(base/10)==0 {
			tong0 = append(tong0, arr[i])
			
		}
		if arr[i]%base/(base/10)==1 {
			tong1 = append(tong1, arr[i])
		}
		if arr[i]%base/(base/10)==2 {
			tong2 = append(tong2, arr[i])
		}
		if arr[i]%base/(base/10)==3 {
			tong3 = append(tong3, arr[i])
		}
		if arr[i]%base/(base/10)==4 {
			tong4 = append(tong4, arr[i])
		}
		if arr[i]%base/(base/10)==5 {
			tong5 = append(tong5, arr[i])
		}
		if arr[i]%base/(base/10)==6 {
			tong6 = append(tong6, arr[i])
		}
		if arr[i]%base/(base/10)==7 {
			tong7 = append(tong7, arr[i])
		}
		if arr[i]%base/(base/10)==8 {
			tong8 = append(tong8, arr[i])
		}
		if arr[i]%base/(base/10)==9 {
			tong9 = append(tong9, arr[i])
		}
	}
	
	arr = append(tong0,tong1...)
	arr = append(arr,tong2...)
	arr = append(arr,tong3...)
	arr = append(arr,tong4...)
	arr = append(arr,tong5...)
	arr = append(arr,tong6...)
	arr = append(arr,tong7...)
	arr = append(arr,tong8...)
	arr = append(arr,tong9...)
	if base*10>1000 {
		return arr
	}
	return jishuSort(arr,base*10)
}

func main() {
	arr := []int{1,17,87,12,2,3,175,958,14,6,8,8,7,1,10,21}
	arr = jishuSort(arr,10)
	fmt.Println(arr)
}

8.归并排序nlogn

package main

import (
	"fmt"
	"time"
	"math/rand"
	
)

func IncorporateArr(left, right []int)[]int{
	i,j :=0,0
	res := []int{}
	ilen,jlen := len(left), len(right)
	for i<ilen&&j<jlen{
		if left[i]<right[j]{
			res = append(res, left[i])
			i++
		}else if left[i]>right[j]{
			res = append(res, right[j])
			j++
		}else{
			res = append(res, left[i])
			res = append(res, right[j])
			i++
			j++
		}
	}
	for i<ilen{
		res = append(res, left[i])
		i++
	}
	for j<jlen{
		res = append(res, right[j])
		j++
	}
	return res
}

func IncorporateSort(arr []int)[]int{
	if len(arr)<=1{
		return arr
	}
	med := len(arr)/2
	left := IncorporateSort(arr[0:med])
	right := IncorporateSort(arr[med:])
	return IncorporateArr(left, right)
}
func MakeArr()[]int{
	var list []int
	re := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0;i<10;i++{
		list = append(list, re.Intn(100))
	}
	return list
}
func main(){
	arr := MakeArr()
	fmt.Println(arr)
	arr = IncorporateSort(arr)
	fmt.Println(arr)
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值