简介
算法学习入门,从排序法开始总是合理的,既基础又重要。我们编写的程序,大部分时间还是跟各种数据打交道,当数据是有序的情况下,更容易处理。
准备工作
为了方便研究各种排序算法的效率,我们需要先编写一个随机数产生函数,参数是随机数个数,上下限和数组本身。在编写的过程中,发现随机数的产生,也是大有学问,出乎我意料。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2019-03-22 10:38:40
# @Author : Promise (promise@mail.ustc.edu.cn)
# @Link : ${link}
# @Version : $Id$
import random
# 如果一开始没定义数组大小,使用注释掉的append,产生100个随机数会特别慢,因此,最好预先定义好数组的长度!
def CreateRandomNumer(n, array, minimun, maximum):
if n > (maximum - minimun + 1):
print('随机数产生失败,没法产生不重复的随机数组')
return False
for i in range(n):
flag = True # 用于处理随机数重复的问题
while flag:
flag = False
# array.append(random.randint(minimun, maximum))
array[i] = random.randint(minimun, maximum)
for j in range(i):
if j == array[i]:
flag = True
break
return True
n, a, b = eval(input('请输入要产生的随机数个数, 最小值,最大值:'))
myArray = [0]*n
isCreated = CreateRandomNumer(n, myArray, a, b)
if isCreated:
print(myArray)
上面的程序,实现的功能是产生完全不重复的随机数。这个程序影响性能的有两个点:
- 数组是否预先确定好长度
- 确定数组是否重复的for循环
一开始使用
array = []
array.append(random.randint(minimun, maximum))
即使是产生100个1到1000之间的数,速度都快得感人(反话谢谢……)
于是,才有了上面的修改,预先确定数组大小,这样一改,数据的产生是瞬间的。
下一步,就是研究for循环的问题了。很显然,当产生的随机数很长的时候,浪费在比较上的时间就会很长,下面的思路,好像是在编程之美提到过,用空间换时间。预先定义一个与待产生数组同长度的布尔数组,每个数字产生了,就标记,之后每产生一个数,就检查该位置是不是已经有数字了,是不是就省去了遍历啊!
实现代码如下,果然速度有了极大的提升
def CreateRandomNumer(n, array, minimun, maximum):
if n > (maximum - minimun + 1):
print('随机数产生失败,没法产生不重复的随机数组')
return False
# 此处增加一个布尔数组
posisionCheck = [False]*(maximum - minimun + 1)
for i in range(n):
flag = True # 用于处理随机数重复的问题, true 表示接下来要继续产生随机数
while flag:
flag = False
# array.append(random.randint(minimun, maximum))
array[i] = random.randint(minimun, maximum)
# 下面的代码是用循环判断不重复,如果变成了用数组来标记呢?
# for j in range(i):
# if j == array[i]:
# flag = True
# break
# 产生的的随机数,减去minimum,就映射到了长度为[0, n-1]的区间
if not posisionCheck[array[i] - minimun]:
posisionCheck[array[i] - minimun] = True
else:
flag = True
# print(posisionCheck)
return True
更改了两个地方,一个是增加布尔数组,
posisionCheck = [False]*(maximum - minimun + 1)
这个数组的长度,是我们要产生随机数的区间,不是要产生随机数的数量,思考下原因~
第二个变化,是关键变动
if not posisionCheck[array[i] - minimun]:
posisionCheck[array[i] - minimun] = True
else:
flag = True
当一个数,第一次出现,肯定能进if语句,把这个数对应的布尔数组的位置,值改为 True,跳出while循环,然后继续产生下一个数;如果出现了重复,flag依然为True,重新产生一个随机数。
敲黑板:这里仅仅是一个查找,操作时间可以认为是常数,而非原始方案的循环。循环是大多数程序运行缓慢的重要原因,所以,大家慎重使用~
这篇文章,到此完结,作为正式介绍排序算法的引子。喜欢的话,欢迎收藏和分享,然后记得点个赞哦~