常见算法
1、冒泡排序

// 冒泡排序 a := []uint8{9, 20, 10, 23, 7, 22, 88, 102} for i := 0; i < len(a); i++ { for k := i + 1; k < (len(a) - i); k++ { if a[i] > a[k] { a[i], a[k] = a[k], a[i] } } } fmt.Println(a)
2、选择排序

// 选择排序 a := []int8{9, 20, -1, 10, -5, 23, 7, 22, 88, 102} for i := 0; i < len(a); i++ { var ( min_n int8 = a[i] min_i int = i ) for k := i + 1; k < len(a); k++ { if a[k] < min_n { min_n = a[k] min_i = k } } a[i], a[min_i] = a[min_i], a[i] } fmt.Println(a)
3、插入排序

a := []int8{9, 20, 22, -1, 10, -5, 23, 7, 7, 22, 88, 102} for i := 1; i < len(a); i++ { for k := i - 1; k >= 0; k-- { if a[k+1] < a[k] { a[k+1], a[k] = a[k], a[k+1] } } } fmt.Println(a)
4、随机数出现的概率为平方
正常来讲,对于[0-10)范围内的任意一个整除的随机数概率为0.1,如果我要实现其中任意一个整数的随机数为0.1^2呢?
下面的示例中,是计算随机数为0-4范围的平方,正常来讲,0-4范围是5个,所以出现的概率为1/2。求其平方,即0.25

// 随机数的概率为平方 var count float64 = 0 for i := 0; i < 100000; i++ { if rand.Intn(10) < 5 { if rand.Intn(10) < 5 { count++ } } } p := count / 100000 fmt.Println(p)
5、这是一个题目:
我当前有一个函数可以等概率随机返回[1-5]之间的任意一个数,在不使用内部函数的前提下,如何只根据当前的这个随机函数来等概率返回[1-7]中的任意一个数呢?
下面是这个随机函数:
func f1() int { rn := rand.Intn(5) + 1 return rn }
解题思路是这样的,可以先构造一个函数,等概率返回0和1,然后再构造一个函数,1-7中的数,可以用三个bit位来表示了,但是还有返回0的时候,当返回0的时候,扔掉,重新来随机
下面是等概率返回0和1的函数:

func f2() int { for { num_1 := f1() if num_1 < 3 { return 0 } else if num_1 == 3 { continue } else { return 1 } } }
下面是返回[1-7]的函数:

func f3() int { for { num_2 := (f2() << 2) + (f2() << 1) + f2() if num_2 == 0 { continue } else { return num_2 } } }
问题来了:
上面我已经用go语言写出了冒泡排序、选择排序和插入排序,我如何验证我所写的代码是否正确呢?当数据量小的时候,我们可以用肉眼去观察,但是这并不代表就是正确的逻辑,当数据量很大的时候呢?其实,在上面的代码中,我对冒泡排序和选择排序的逻辑是有问题的,是错误的;我们如何验证呢?这时候我们需要用到的就是对数器,通过对数器我们就可以不断的去验证我的代码,数据量大小也是可控的。
下面是我编写的对数器及各个排序的函数,其中三个排序函数是经过验证而改正的:

package main import ( "fmt" "math/rand" ) func main() { // 对数器,生成随机样本,自己做比对的机器,通过对数器,可以调出所有错误来 var ( lenth int = 10 maxValue int = 1000 testTimes int = 10 ) for i := 0; i < testTimes; i++ { src_sli := rlrv(lenth, maxValue) sort_sli := insertSort(src_sli) // sort_sli := bubbleSort(src_sli) // sort_sli := chooseSort(src_sli) if !isSorted(sort_sli) { fmt.Println("Sort is false") // 这里如果排序不正确,则返回false } } } // 选择排序 func chooseSort(sli []int) []int { for i := 0; i < len(sli)-1; i++ { var ( min_n int = sli[i] min_i int = i ) for k := i + 1; k < len(sli); k++ { if sli[k] < min_n { min_n = sli[k] min_i = k } } sli[i], sli[min_i] = sli[min_i], sli[i] } return sli } // 插入排序 func insertSort(sli []int) []int { for i := 1; i < len(sli); i++ { for k := i - 1; k >= 0; k-- { if sli[k+1] < sli[k] { sli[k+1], sli[k] = sli[k], sli[k+1] } } } return sli } // 冒泡排序 func bubbleSort(sli []int) []int { for i := 1; i < len(sli); i++ { for k := 1; k < len(sli); k++ { if sli[k-1] > sli[k] { sli[k-1], sli[k] = sli[k], sli[k-1] } } } return sli } // 是否已排序 func isSorted(sli []int) bool { if len(sli) == 0 { return true } for i := 0; i < len(sli)-1; i++ { if sli[i] > sli[i+1] { return false } } return true } // 此处暂未使用,后面会用 func copySli(sli []int) []int { newSli := make([]int, len(sli)) copy(newSli, sli) return newSli } // 生成一个随机切片 func rlrv(lenghth int, value int) []int { sli := make([]int, lenghth) for i := 0; i < len(sli); i++ { sli[i] = rand.Intn(value) + 1 } return sli } 对数器
对于上面代码还是可以继续优化的,根据自己需求添加不同功能,比如我想知道排序函数用时多久,可以添加startTime和endTime,然后相减。通过查看时间可以了解到,对于上面三个排序函数,其中选择排序相比用时较短
sort包
Go的标准库提供了sort库,用来给线性数据结构排序、二分查找。
a := []int{-1, 23, 5, 9, 7} // sort.Sort(sort.IntSlice(a)) // sort.IntSlice(a)强制类型转换以施加接口方法 sort.Ints(a) // 就地修改原切片的底层数组 fmt.Println(a) // 默认升序 b := []string{"xyz", "a", "abc", "Ab", "X"} sort.Strings(b) fmt.Println(b) // 降序 sort.Sort(sort.Reverse(sort.IntSlice(a))) fmt.Println(a)
// 二分查找 a := []int{-1, 23, 5, 9, 7} sort.Ints(a) // 二分查找,必须是升序 // 二分查找的前提是 有序 i := sort.SearchInts(a, 7) fmt.Println(i)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!