今天开始,就要刷一本算法的入门书了,我自认自身的资质不行,所以踏踏实实的,一步一步的去走,我会把书中的前提例子摘出来,然后自己去实现出来。
这是一本很有趣的书,久仰大名,所以就买来看,希望能让我的算法有一定进步,培养出我对算法的兴趣来,也推荐给各位观看。
另外,由于我现在在学习java、python、go的基础,所以可能会列出这三个语言的代码。
排序
第1节 最快最简单的排序——桶排序
这个思想是简化版的桶排序,首先看例子
需求就是:满分是10分,我们要把这五位同学的分数按从高到低排序。
那么我们应该怎么做呢?
首先我们需要申请一个大小为 11 的数组 int a[11]。 OK,现在你已经有了 11 个变量,编
号从 a[0]~a[10]。刚开始的时候,我们将 a[0]~a[10]都初始化为 0,表示这些分数还都没有人
得过。例如 a[0]等于 0 就表示目前还没有人得过 0 分,同理 a[1]等于 0 就表示目前还没有人
得过 1 分……a[10]等于 0 就表示目前还没有人得过 10 分。
因为我们的满分为10,所以我们创建了0-10一共11个数长度的数组,然后我们就对这五个人的分数进行遍历,如果分数是1分,就在a[1]的基础上加1,代表出现过一次,如果分数是2分,就在a[2]的基础上加1,如此。
最终可能就是这样的,2分的1位同学,3分的一位同学,5分的两位同学,8分的一位同学,然后我们在把a[0] ~ a[10]中的数值按次数打印出来就可以了。
a[0]为 0,表示“ 0”没有出现过,不打印。
a[1]为 0,表示“ 1”没有出现过,不打印。
a[2]为 1,表示“ 2”出现过 1 次,打印 2。
a[3]为 1,表示“ 3”出现过 1 次,打印 3。
a[4]为 0,表示“ 4”没有出现过,不打印。
a[5]为 2,表示“ 5”出现过 2 次,打印 5 5。
a[6]为 0,表示“ 6”没有出现过,不打印。
a[7]为 0,表示“ 7”没有出现过,不打印。
a[8]为 1,表示“ 8”出现过 1 次,打印 8。
a[9]为 0,表示“ 9”没有出现过,不打印。
a[10]为 0,表示“ 10”没有出现过,不打印。
最终屏幕输出“ 2 3 5 5 8”。
这个算法就好比有11个桶,编号从0~10,每出现一个数,就在对应编号的桶中放一个小旗子,最后只需要数数每个桶中有几个小旗子就OK了。
// java
public static void main(String[] args) {
// 初始化数组,数组是引用数据类型,对于引用数据类型,java会有默认值,所以不需要我们赋值为0了。
int[] a = new int[11];
// 初始化随机数
Random rn = new Random();
for(int i = 0; i < 5; i ++) {
// rn.nextInt会获取0 - 10的一个随机数,我们让这个分数的次数加1
int num = rn.nextInt(11);
a[num] = a[num] + 1;
}
// 打印出数据,从小到大
for(int i = 0; i < 11; i ++) { // 依次判断a[0] ~ a[10]
for(int j = 0; j < a[i]; j++) { // 出现了几次就打印几次
System.out.print(i + " ");
}
}
// 空一行
System.out.println();
// 打印出数据,从大到小
for(int i = 10; i >= 0 ; i --) { // 依次判断a[10] ~ a[0]
for(int j = 0; j < a[i]; j++) { // 出现了几次就打印几次
System.out.print(i + " ");
}
}
}
# python
import random
if __name__ == '__main__':
a = list(range(11)) # 创建一个11个长度(0-10)的list
for i in range(11): # 让这个list的每一个桶的标记都为0
a[i] = 0
for i in range(5): # 生成五个随机数,并让对应的a list对应的桶中放一个旗子。
num = random.randint(0,10)
a[num] = a[num] + 1
# 从小到大排序
for i in range(11): # 检查0 - 10这11个桶
for j in range(a[i]): # 如果有一个旗子就打印一次这个桶的号码,如果有两个旗子就打印两次。
print(i)
print("\n") # 空行
# 从大到小排序
for i in range(10,-1,-1): # 检查10 ~ 0 这11个桶。 最后一个-1参数代表递减,10,-1 是这样表示的[10,-1)
for j in range(a[i]): # 如果有一个旗子就打印一次这个桶的号码,如果有两个旗子就打印两次。
print(i)
// go
package main
import "fmt"
import "math/rand"
func main(){
var a [11]int // 创建一个11个长度的数组,它们的初始值就为0
var i,j,temp int // 初始化变量
// 生成五个随机数,并且在0-10号桶中放旗子
for i = 0; i < 5; i++ {
temp = rand.Intn(10)
a[temp] = a[temp] + 1
}
// 遍历从0-10号桶,有几个旗子就打印几次这个桶的序号
// 从小到大排序
for i = 0; i < 11; i++{
for j = 0; j < a[i]; j++{
fmt.Print(i)
fmt.Print(" ")
}
}
// 空行
fmt.Print("\n")
// 从大到小排序
for i = 10; i >= 0; i--{
for j = 0; j < a[i]; j++{
fmt.Print(i)
fmt.Print(" ")
}
}
}