【算法排序】代码注释和解析( 1冒泡排序 2选择排序 3插入排序 4快速排序 )
本文主要针对下述4种不同的排序类型,进行代码的注释和解析:
1冒泡排序
2选择排序
3插入排序
4快速排序
冒泡排序
1、方法1:中间变量
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' import random,time #随机产生50个随机数(在1-100之间) array=[] for i in range(1000): pass a = random.randrange(1,10001) #random.randrange([start], stop[, step]), 左闭右开 # 从指定范围内,按指定基数递增的集合中 获取一个随机数。 # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # a = random.random() #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0 # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20 左闭右闭 array.append(a) #随机数添加到空列表 # print(array) #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装pycharm可以解决) #临时解决办法:列表比较大的时候,不打印排序后的列表 # array = [871,100,160,755] def bubble_sort(array): count=0 for i in range(1,len(array)): #外循环,循环列表长度-1次即可(列表长度是4,循环3次即可) # 第一次内循环先把最大的放在最后,第二次内循环先把第二大的放在倒数第二,。。。。依次类推 #参数从1开始,遍历的是列表的长度,而不是遍历的列表本身 #参数从0开始,遍历的是列表的本身,而不是列表的长度 for j in range(len(array)-i): #i=1 len(array)=4 range=3(0,1,2) #内循环,相邻的2个数比较,大的数放在右边(1和2比较,2和3比较。。。。) if array[j] > array[j+1]: tmp = array[j] #这里采用了一个中间变量,也可以直接交换 array[j] = array[j+1] array[j+1] = tmp count+=1 print("执行次数:%s" % count) start_time = time.time() bubble_sort(array) end_time=time.time() print("执行花费时间(单位秒):%s" % (end_time-start_time)) #计算执行时间 # print(array) #[100, 160, 755, 871] # for i in range(1,4): # print(i) #1,2,3 左闭又开 range # for i in range(3): # print(i) #0,1,2 #涉及知识点 #1函数 #2产生5w随机数 random #3冒泡排序执行次数 count #4冒泡排序执行时间 time #5冒泡算法
2、方法2:直接交换
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' import random,time #随机产生50个随机数(在1-100之间) array=[] for i in range(5000): pass a = random.randrange(1,101) #random.randrange([start], stop[, step]), 左闭右开 # 从指定范围内,按指定基数递增的集合中 获取一个随机数。 # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # a = random.random() #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0 # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20 左闭右闭 array.append(a) #随机数添加到空列表 # print(array) #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决) #临时解决办法:列表比较大的时候,不打印排序后的列表 # array = [871,100,160,755] def bubble_sort(array): count=0 for i in range(1,len(array)): #外循环,循环列表长度-1次即可(列表长度是4,循环3次即可) for j in range(len(array)-i): #i=1 len(array)=4 range=3(0,1,2) #内循环,相邻的2个数比较,大的数放在右边(1和2比较,2和3比较。。。。) if array[j] > array[j+1]: # tmp = array[j] #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 31行 # array[j] = array[j+1] # array[j+1] = tmp array[j],array[j+1] = array[j+1],array[j] count+=1 print("执行次数:%s" % count) start_time = time.time() bubble_sort(array) end_time=time.time() print("执行花费时间(单位秒):%s" % (end_time-start_time)) #计算执行时间 # print(array) #[100, 160, 755, 871] # for i in range(1,4): # print(i) #1,2,3 左闭又开 range # for i in range(3): # print(i) #0,1,2 #涉及知识点 #1函数 #2产生5w随机数 random #3冒泡排序执行次数 count #4冒泡排序执行时间 time #5冒泡算法
3、方法3:减少交换次数,相对高效
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' import random,time #随机产生50个随机数(在1-100之间) array=[] for i in range(10000): pass a = random.randrange(1,10001) #random.randrange([start], stop[, step]), 左闭右开 # 从指定范围内,按指定基数递增的集合中 获取一个随机数。 # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # a = random.random() #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0 # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20 左闭右闭 array.append(a) #随机数添加到空列表 # print(array) #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决) #临时解决办法:列表比较大的时候,不打印排序后的列表 # array = [871,100,160,755] def bubble_sort(array): count=0 for i in range(len(array)): #外循环,循环列表长度-1次即可(列表长度是4,循环3次即可) # 第一次内循环先把最大的放在最后,第二次内循环先把第二大的放在倒数第二,。。。。依次类推 smallest_index = i #外循环,假设当前位置的下标对应的那个数是最小的 for j in range(i,len(array)): #i=1 len(array)=4 range=3(0,1,2) #内循环,相邻的2个数比较,大的数放在右边(1和2比较,2和3比较。。。。) if array[smallest_index] > array[j]: #如果外循环当前位置的下标对应的那个数 比内循环的其中一个数大 #说明外循环当前位置的下标对应的那个数不是最小的,需要和内循环中的那个数交换位置 # tmp = array[j] #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 33行 # array[j] = array[j+1] # array[j+1] = tmp # array[j],array[j+1] = array[j+1],array[j] smallest_index=j #把内循环中的那个数的小标置为最小数下标 count+=1 tmp = array[i] array[i] = array[smallest_index] array[smallest_index] = tmp #交换次数只会在外循环中进行,在内循环不进行,显著减少了交换次数(执行次数减少是关键) print("执行次数:%s" % count) start_time = time.time() bubble_sort(array) end_time=time.time() print("执行花费时间(单位秒):%s" % (end_time-start_time)) #计算执行时间 # print(array) #[100, 160, 755, 871] # for i in range(1,4): # print(i) #1,2,3 左闭又开 range # for i in range(3): # print(i) #0,1,2 #涉及知识点 #1函数 #2产生5w随机数 random #3冒泡排序执行次数 count #4冒泡排序执行时间 time #5冒泡算法
二、选择排序
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' import random,time #随机产生50个随机数(在1-100之间) array=[] for i in range(5000): pass a = random.randrange(1,101) #random.randrange([start], stop[, step]), 左闭右开 # 从指定范围内,按指定基数递增的集合中 获取一个随机数。 # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # a = random.random() #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0 # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20 左闭右闭 array.append(a) #随机数添加到空列表 # print(array) #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决) #临时解决办法:列表比较大的时候,不打印排序后的列表 # array = [871,100,160,755] #选择排序的思想: #内循环:每个数都和左边第一个数对比,如果小于左边第一个数,就交换位置 57行 #外循环:每个数都和左边第二个数对比,如果小于左边第二个数,就交换位置; # 每个数都和左边第三个数对比,如果小于左边第三个数,就交换位置; # 首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素, # 然后放到排序序列末尾。以此递归。 def selection_sort(array): count=0 for i in range(len(array)): #外循环,循环列表本身(列表长度是4,循环4次即可) for j in range(i,len(array)): #i=1 len(array)=4 range=3(0,1,2) if array[j] < array[i]: #[100, 160, 755, 871] 从小到大 #外循环的数不变,那内循环的每一个数和外循环的数对比大小 # if array[j] > array[i]: #[100, 160, 755, 871] 从大到小 tmp = array[i] #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 31行 array[i] = array[j] array[j] = tmp # array[j],array[j+1] = array[j+1],array[j] count+=1 print("执行次数:%s" % count) start_time = time.time() selection_sort(array) end_time=time.time() print("执行花费时间(单位秒):%s" % (end_time-start_time)) #计算执行时间 # print(array) #[100, 160, 755, 871] # for i in range(1,4): # print(i) #1,2,3 左闭又开 range # for i in range(3): # print(i) #0,1,2 #涉及知识点 #1函数 #2产生5w随机数 random #3排序执行次数 count #4排序执行时间 time #5选择排序算法 # Example. # # 29, 64, 73, 34, 20, # 20, 64, 73, 34, 29, # 20, 29, 73, 34, 64 # 20, 29, 34, 73, 64 # 20, 29, 34, 64, 73
三、插入排序
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' import random,time #随机产生50个随机数(在1-100之间) array=[] for i in range(5000): pass a = random.randrange(1,5001) #random.randrange([start], stop[, step]), 左闭右开 # 从指定范围内,按指定基数递增的集合中 获取一个随机数。 # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # a = random.random() #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0 # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20 左闭右闭 array.append(a) #随机数添加到空列表 # print(array) #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决) #临时解决办法:列表比较大的时候,不打印排序后的列表 array = [871,100,160,755] # 插入排序(Insertion Sort)的基本思想是:将列表分为2部分,左边为排序好的部分,右边为未排序的部分,循环整个列表, # 每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。 def insertion_sort(array): count=0 for i in range(1,len(array)): #外循环,循环列表的长度(列表长度是4,循环3次即可) tmp = array[i] #先记下来每次外循环走到的第几个元素的值 # for j in range(i,len(array)): #i=1 len(array)=4 range=3(0,1,2) # if array[j] < array[i]: #[100, 160, 755, 871] 从小到大 # #外循环的数不变,那内循环的每一个数和外循环的数对比大小 # # if array[j] > array[i]: #[100, 160, 755, 871] 从大到小 # tmp = array[i] #这里采用了一个中间变量(好理解),也可以直接交换(简洁) 31行 # array[i] = array[j] # array[j] = tmp # # array[j],array[j+1] = array[j+1],array[j] # count+=1 while i>0 and array[i-1] > tmp: #当前元素的左边的紧靠的元素比它大,要把左边的元素一个一个的往右移一位,给当前这个值插入到左边挪一个位置出来 # while i>0 and array[i-1] < tmp: #当前元素的左边的紧靠的元素比它大,要把左边的元素一个一个的往右移一位,给当前这个值插入到左边挪一个位置出来 # tmp = array[i] array[i] = array[i-1] ##把左边的一个元素往右移一位 i -= 1 #只一次左移只能把当前元素一个位置 ,还得继续左移直到此元素放到排序好的列表的适当位置 为止 count+=1 array[i] = tmp #已经找到了左边排序好的列表里不小于tmp的元素的位置,把tmp放在这里 print("执行次数:%s" % count) # count=0 # for index in range(1,len(array)): # current_val = array[index] #先记下来每次大循环走到的第几个元素的值 # position = index # # while position > 0 and array[position-1] > current_val: #当前元素的左边的紧靠的元素比它大,要把左边的元素一个一个的往右移一位,给当前这个值插入到左边挪一个位置出来 # array[position] = array[position-1] #把左边的一个元素往右移一位 # position -= 1 #只一次左移只能把当前元素一个位置 ,还得继续左移只到此元素放到排序好的列表的适当位置 为止 # count+=1 # array[position] = current_val #已经找到了左边排序好的列表里不小于current_val的元素的位置,把current_val放在这里 # # print(array) # print("执行次数:%s" % count) start_time = time.time() insertion_sort(array) end_time=time.time() print("执行花费时间(单位秒):%s" % (end_time-start_time)) #计算执行时间 print(array) #[100, 160, 755, 871] # for i in range(1,4): # print(i) #1,2,3 左闭又开 range # for i in range(3): # print(i) #0,1,2 #涉及知识点 #1函数 #2产生5w随机数 random #3排序执行次数 count #4排序执行时间 time #5插入排序算法 # Example. # # 结果: # [77, 92, 67, 8, 6, 84, 55, 85, 43, 67] # [67, 77, 92, 8, 6, 84, 55, 85, 43, 67] # [8, 67, 77, 92, 6, 84, 55, 85, 43, 67] # [6, 8, 67, 77, 92, 84, 55, 85, 43, 67] # [6, 8, 67, 77, 84, 92, 55, 85, 43, 67] # [6, 8, 55, 67, 77, 84, 92, 85, 43, 67] # [6, 8, 55, 67, 77, 84, 85, 92, 43, 67] # [6, 8, 43, 55, 67, 77, 84, 85, 92, 67] # [6, 8, 43, 55, 67, 67, 77, 84, 85, 92]
四、快速排序
#!/usr/bin/env python #-*- coding:utf-8 -*- __author__ = 'Administrator' import random,time #随机产生50个随机数(在1-100之间) array=[] for i in range(5000): pass a = random.randrange(1,5001) #random.randrange([start], stop[, step]), 左闭右开 # 从指定范围内,按指定基数递增的集合中 获取一个随机数。 # 如:random.randrange(10, 100, 2),结果相当于从[10, 12, 14, 16, ... 96, 98]序列中获取一个随机数。 # a = random.random() #random.random()用于生成一个0到1的随机浮点数: 0 <= n < 1.0 # a = random.randint(1,10) #printrandom.randint(12,20)#生成的随机数n:12<=n<=20 左闭右闭 array.append(a) #随机数添加到空列表 # print(array) #注意:这里pycharm打印5w随机数据比较的慢,pycharm本身的问题(重装可以解决) #临时解决办法:列表比较大的时候,不打印排序后的列表 # array = [871,100,160,755] #快速排序基本思想:第一次递归:以第一个元素为基准,大于基准的数放在右边,小于基准的数放在左边 #第二次递归:以基准作为分割线,将列表一分为二,列表左边以第一个元素为基准,大于基准的数放在右边,小于基准的数放在左边 # 列表右边以第一个元素为基准,大于基准的数放在右边,小于基准的数放在左边 # 注意:第一遍快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。为了得到最后结果, # 需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。 def quick_sort(array,left,right): ''' :param array: :param left: 列表的第一个索引 :param right: 列表最后一个元素的索引 :return: ''' count=0 if left >=right: return #递归退出条件 low = left high = right key = array[low] #第一个值 while low < high:#只要左右未遇见 while low < high and array[high] > key: #找到列表右边比key大的值 为止 high -= 1 #此时直接 把key(array[low]) 跟 比它大的array[high]进行交换 array[low] = array[high] array[high] = key while low < high and array[low] <= key : #找到key左边比key大的值 low += 1 #array[low] = #找到了左边比k大的值 ,把array[high](此时应该刚存成了key) 跟这个比key大的array[low]进行调换 array[high] = array[low] array[low] = key count+=1 quick_sort(array,left,low-1) #最后用同样的方式对分出来的左边的小组进行同上的做法 递归 quick_sort(array,low+1, right)#用同样的方式对分出来的右边的小组进行同上的做法 递归 # print("执行次数:%s" % count) start_time = time.time() quick_sort(array,0,len(array)-1) end_time=time.time() print("执行花费时间(单位秒):%s" % (end_time-start_time)) #计算执行时间 print(array) #[100, 160, 755, 871] # for i in range(1,4): # print(i) #1,2,3 左闭又开 range # for i in range(3): # print(i) #0,1,2 #涉及知识点 #1函数 #2产生5w随机数 random #3排序执行次数 count #4排序执行时间 time #5快速排序算法 # Example. # # 结果:
排序演示
示例
假设用户输入了如下数组:
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
数据
|
6
|
2
|
7
|
3
|
8
|
9
|
创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。
我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:
下标
|
0
|
1
|
2
|
3 |
4
|
5
|
数据
|
3
|
2
|
7
|
6
|
8
|
9
|
i=0 j=3 k=6
接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
数据
|
3
|
2
|
6
|
7
|
8
|
9
|
i=2 j=3 k=6
称上面两次比较为一个循环。
接着,再递减变量j,不断重复进行上面的循环比较。
在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
数据
|
3
|
2
|
6
|
7
|
8
|
9
|
如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。