《啊哈!算法》 第一章:排序


今天开始,就要刷一本算法的入门书了,我自认自身的资质不行,所以踏踏实实的,一步一步的去走,我会把书中的前提例子摘出来,然后自己去实现出来。

这是一本很有趣的书,久仰大名,所以就买来看,希望能让我的算法有一定进步,培养出我对算法的兴趣来,也推荐给各位观看。

另外,由于我现在在学习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(" ")
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_29582443/article/details/107899290
今日推荐