冒泡排序描述

重复列表进行排序,比较每对相邻的项目,如果他们的顺序错误,则进行交换
在完成每一趟的排序时,最大元素已被‘冒泡’到数列末端的合适位置
重复列表,直到不需要交换,这表明列表已被排序

一、模块准备

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 Butterworth详解_数据结构


Python Butterworth详解_数据结构_02


当我们要在本地找配置文件的时候,它放在哪呢?

可以在python安装好的Lib文件夹里面:python\Lib\site-packages\matplotlib\mpl-data(这是我自己的本地路径)

Python Butterworth详解_算法_03


可以打开之后看看里面关于图表当中字体和负号的配置

Python Butterworth详解_算法_04


Python Butterworth详解_数据结构_05


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,放在列表后面

直到完全排序

Python Butterworth详解_数据分析_06

二、了解了原理之后,来正式开始整个程序的设计

捋一捋整体思路:
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)

四、具体运行效果及图表生成

Python Butterworth详解_数据结构_07


Python Butterworth详解_数据分析_08


Python Butterworth详解_数据结构_09


Python Butterworth详解_数据结构_10


Python Butterworth详解_数据分析_11


测试用例准备好了之后,程序会绘制出两种方法的时间对比,如下图所示,差距已经很明显了:

Python Butterworth详解_冒泡排序_12

文章仅用于学习交流,转载请注明出处,谢谢!