posts - 177,comments - 14,views - 40万

常见算法

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
        }
    }
}
f2
复制代码

下面是返回[1-7]的函数:

复制代码
func f3() int {
    for {
        num_2 := (f2() << 2) + (f2() << 1) + f2()
        if num_2 == 0 {
            continue
        } else {
            return num_2
        }
    }
}
f3()
复制代码

 问题来了:

上面我已经用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)

 

posted on   自然洒脱  阅读(100)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示