【学习笔记】用python实现bubblesort以及shakersort

冒泡排序的原理不多说,先看python版的bubblesort:

#!/usr/bin/python
import sys


n = len(sys.argv) - 1


for i in range(n, 0, -1):	# n to 1
	for j in range(1, i):	# 1 to i-1
		if int(sys.argv[j], 10) > int(sys.argv[j+1], 10):   # [C]
			tmp = sys.argv[j]                           # [M]
			sys.argv[j] = sys.argv[j+1]                 # [M]
			sys.argv[j+1] = tmp                         # [M]


	print sys.argv

算法最佳情况下只进行数据的比较,即初始数组已经排好序,只执行代码中[C]步骤,一共进行n*((n+1)/2*1)次,此时时间复杂度为O(N^2)。算法最差情况下要进行数据的比较[C]和移动[M],虽然时间复杂度同样为O(N^2),但是每次比较之后都会进行三次数据移动,一共执行n*((n+1)/2*4)次比较和移动。

传统的冒泡排序缺点在于排序类似[2,3,4,5,1]数列的时候,要循环多次,如下所示:
[2,3,4,5,1]
[2,3,4,1,5]
[2,3,1,4,5]
[2,1,3,4,5]
[1,2,3,4,5]

可以看出,只是为了移动一个数而不得不分成四次完成,如果一开始从右往左遍历,一次排序即可完成,因此我们可以加上一个反向遍历的冒泡排序,当从左遍历到右边之后不是立即再从左往右遍历,而是从右边往左边做冒泡排序,代码如下:

#!/usr/bin/python
import sys

n = len(sys.argv) - 1

for i in range(n, 0, -1):	# n to 1
	for j in range(1, i):	# 1 to i-1
		if int(sys.argv[j], 10) > int(sys.argv[j+1], 10):        # [C]
			tmp = sys.argv[j]                                # [M]
			sys.argv[j] = sys.argv[j+1]                      # [M]
			sys.argv[j+1] = tmp                              # [M]

	# shakersort, this part can improve bubblesort in some cases
	for j in range(i - 1, 0, -1):	# i-1 to 1
		if int(sys.argv[j], 10) > int(sys.argv[j+1], 10):        # [C]
			tmp = sys.argv[j]                                # [M]
			sys.argv[j] = sys.argv[j+1]                      # [M]
			sys.argv[j+1] = tmp                              # [M]

	print sys.argv

算法最佳情况下只进行数据的比较,即初始数组已经排好序,只进行代码中[C]步骤,一共进行n*((n+1)/2*2)次,此时时间复杂度为O(N^2)。算法最差情况下要进行数据的比较[C]和移动[M],虽然时间复杂度同样为O(N^2),但是每次比较之后都会进行三次数据移动,一共进行n*((n+1)/2*8)次比较和移动。

对[2,3,4,5,1]数列进行排序,过程如下:

[2,3,4,5,1]

[1,2,3,4,5]

[1,2,3,4,5]

[1,2,3,4,5]

[1,2,3,4,5]

改进的优点:对类似上述数列的排序进行排序时,减少了数据的移动。

缺点:增加了比较的次数。

可能的改进:可以看出加入shakersort之后对[2,3,4,5,1]进行排序时,数列很快就被排好序,如果能提前检测到数列已经被排好序,那么就可以提前停止算法,这样大大减少比较的次数和算法执行的时间。

以下是对算法进行改进后的代码:

#!/usr/bin/python
import sys

n = len(sys.argv) - 1

l = 1
r = n
for i in range(l, r/2+1):	# 只需要进行n/2次双向冒泡排序
	is_sorted = 1
	for j in range(l, r):   # 从左往右冒泡
		if int(sys.argv[j], 10) > int(sys.argv[j + 1], 10):
			tmp = sys.argv[j]
			sys.argv[j] = sys.argv[j + 1]
			sys.argv[j+1] = tmp
			is_sorted = 0  # 如果还存在数据交换,说明数列还没排好序

	# shakersort, this part can improve bubblesort
	for j in range(r - 1, l, -1):  # 从右往左冒泡
		if int(sys.argv[j], 10) < int(sys.argv[j - 1], 10):
			tmp = sys.argv[j]
			sys.argv[j] = sys.argv[j - 1]
			sys.argv[j - 1] = tmp
			is_sorted = 0  # 如果还存在数据交换,说明数列还没排好序
	if(is_sorted):  # 检查数列是否已经排好序
		break;
	l = l + 1
	r = r - 1
	print sys.argv

用以上算法对数列[1,2,3,4,5,6,7,0]进行排序,输出如下:

[0,1,2,3,4,5,6,7]

此时达到冒泡排序的最优状态,即分别对[7,0,1,2,3,4,5,6]和[1,2,3,4,5,6,7,0]排序都是一次循环结束战斗。

点赞