冒泡排序描述
重复列表进行排序,比较每对相邻的项目,如果他们的顺序错误,则进行交换
在完成每一趟的排序时,最大元素已被‘冒泡’到数列末端的合适位置
重复列表,直到不需要交换,这表明列表已被排序
一、模块准备
1、前期准备
为了让程序更加的灵活,在准备数据样本时我采用随机数的形式,可以让程序根据自己想要生成的规模及随机范围进行数组的生成,这样更具一般性,加入时间模块和matplotlib进行可视化比对
import random
import time
import matplotlib.pyplot as plt
准备四组空列表用来接收对应的数据
bubble_num = [] # 生成的随机数组
bubble_num_scale = [] # 数组规模存储
bubble_sort_time_before = [] # 普通冒泡对应规模的时间
bubble_sort_time_after = [] # 优化之后的对应时间
2、开始控制输入规模
为了方便管理控制,将随机数组封装到函数体当中,考虑到用户的输入是有很大灵活性的,将异常处理加入其中,不满足条件的及时抛出异常。
每一次输入的列表规模都存入专门的列表当中,方便后序matplotlib处理
def input_num():
'''
控制产生随机数列表
:return: bubble_num
'''
global num, start, end
num = int(input('请输入产生数组的个数:'))
if num <= 0:raise Exception('请输入大于零的数字')
start = int(input('请输入起始数字:'))
end = int(input('请输入结束数字:'))
if start > end :raise Exception('起始数字一定要小于结束数字')
# 专门存入记录规模的列表
bubble_num_scale.append(num)
for i in range(num):
n = random.randint(start, end)
bubble_num.append(n)
return bubble_num
3、构造图表
同样,为了日后的管理扩展,封装到函数体当中
# 创建冒泡排序优化前后时间对比图表
def create_figure(scale, t1, t2):
plt.figure(figsize=(8, 6))
plt.style.use('ggplot') # 设置图表风格
# 设置x,y轴的样式以及标签
plt.xticks(size=15, color='red')
plt.yticks(size=15, color='blue')
plt.xlabel('array scale', size=20, color='black')
plt.ylabel('time(s)', size=20, color='black')
# 设置图表标题
plt.title('优化前后时间对比', fontsize='30', color='black')
# 调用plot函数,传入两组数据
plt.plot(scale, t1)
plt.plot(scale, t2)
# 设置图表的图例,确定前后对比
plt.legend(labels=['before', 'after'])
# 解决图表不能显示汉字问题,和负号问题,修改rc配置
plt.rcParams['font.sans-serif'] = 'SimHei' # 黑体
plt.rcParams['axes.unicode_minus'] = False # 默认是不显示负号的,配置文件默认值为True
plt.show()
那rcParams到底是什么呢?
rcParams实际上plot是使用rc配置文件来自定义图形的各种默认属性,称之为rc配置或rc参数.通过rc参数可以修改默认的属性,包括窗体大小、每英寸的点数、线条宽度、颜色、样式、坐标轴、坐标和网络属性、文本、字体等
matplotlib的配置文件可以在本地资源管理器里面找到,也可以用print(matplotlib.rcParams)打印出来
使用print(matplotlib.rcParams)
当我们要在本地找配置文件的时候,它放在哪呢?
可以在python安装好的Lib文件夹里面:python\Lib\site-packages\matplotlib\mpl-data(这是我自己的本地路径)
可以打开之后看看里面关于图表当中字体和负号的配置
4、图表的问题解决之后,开始代码的书写
先举个小例子,简单实现冒泡排序
bubble_num = [6, -3, 9, 10, 26, 8, 13, -4]
for i in range(len(bubble_num)):
for j in range(len(bubble_num) - i - 1):
if bubble_num[j] > bubble_num[j + 1]:
bubble_num[j], bubble_num[j + 1] = bubble_num[j + 1], bubble_num[j]
print(bubble_num)
第一趟首先6和-3进行比较,6>-3,进行交换,此时6和9进行比较,6<9,顺序不动,接着9和10,10和26都是同理,当26和8比较的时候,互换位置,26和13也互换,26和-4也互换,这样第一趟遍历交换结束,之后的遍历,同理
第一趟,26最大,放到列表莫问
第二趟,在剩下的列表中遍历,找到13放在后面
第三趟,找到10,放在列表后面
直到完全排序
二、了解了原理之后,来正式开始整个程序的设计
捋一捋整体思路:
1、第一部分实现自定义随机数组的创建,这个在上面的内容已经完成
2、第二部分创建所需图表,封装到函数体当中,用户输入的规模作为第一个参数传入create_figure方法体中,一般的冒泡实现所消耗时间和优化之后的时间分别作为第二、第三个参数传入方法体中
3、第三部分,实现正常情况下的冒泡排序
4、第四部分,加入交换标记,实现冒泡排序的优化
5、第五部分,进行用户交互的简易实现
前两部上面的部分已经搞定了,
接下来实现3、4步
def bubble_sort(bubble_num):
'''
开始冒泡排序,时间复杂度在O(n^2),可以做优化
:param bubble_num:
:return: bubble_num and time
'''
start_time = time.time()
for i in range(len(bubble_num)):
for j in range(len(bubble_num) - i - 1):
if bubble_num[j] > bubble_num[j + 1]:
bubble_num[j], bubble_num[j + 1] = bubble_num[j + 1], bubble_num[j]
end_time = time.time()
t = end_time - start_time
return bubble_num, t
def better_bubble_sort(bubble_num):
'''
做优化的时候可以设置一个标记,如果这一趟不发生任何的交换,那可以直接跳出当前循环,进行下一次循环
:param bubble_num:
:return: bubble_num and time
'''
start_time = time.time()
for i in range(len(bubble_num)):
isSorted = True
for j in range(len(bubble_num) - i - 1):
if bubble_num[j] > bubble_num[j + 1]:
bubble_num[j], bubble_num[j + 1] = bubble_num[j + 1], bubble_num[j]
isSorted = False
if isSorted: break
end_time = time.time()
t = end_time - start_time
return bubble_num, t
优化的操作很简单,加入交换标记判断之后,如果某一趟的顺序已经没有发生交换了,那直接跳出当前循环,进入下一趟,减少重复性工作
三、主程序实现
while True:
ifStart = input('请按下任意按键开始冒泡排序(若想退出,请按字母Q键):')
if ifStart == 'Q' or ifStart == 'q': break
# 开始输入
res = input_num()
print('before bubble sort\n%s' % res)
# 普通冒泡排序
result = bubble_sort(bubble_num)
print('after bubble sort \n%s\n time:%.20f s' % (result[0], result[1]))
bubble_sort_time_before.append(result[1])
# 优化后的冒泡排序
result1 = better_bubble_sort(bubble_num)
print('after optimize the bubble sort\n%s\n time:%.20f s' % (result1[0], result1[1]))
bubble_sort_time_after.append(result1[1])
print('-' * 40)
# 输入结束,开始数据可视化分析
# 打印一下存放数据的列表,确定数据是否有误,是否需要调整
print(bubble_num_scale)
print(bubble_sort_time_before)
print(bubble_sort_time_after)
create_figure(bubble_num_scale, bubble_sort_time_before, bubble_sort_time_after)
四、具体运行效果及图表生成
测试用例准备好了之后,程序会绘制出两种方法的时间对比,如下图所示,差距已经很明显了:
文章仅用于学习交流,转载请注明出处,谢谢!