#排序算法,2018.9.15
def bubble_sort(alist):
'''冒泡排序'''
#平均情况:O(n^2)
#最优时间复杂度:O(n)
#最坏时间复杂度:O(n^2)
#辅组空间:O(1)
#稳定性:稳定
n = len(alist)
for j in range(n-1):
#游标
count = 0
#每循环一次,最大值在最后,接下来排序n-1,n-2
for i in range(n-1-j):
if alist[i] > alist[i+1]:
#如果前面的大于后边的,交换位置
alist[i], alist[i+1] = alist[i+1], alist[i]
#如果有序,游标向后移动一位
count += 1
#优化,已有序序列
if count == 0:
return
def select_sort(alist):
'''选择排序'''
#平均情况:O(n^2)
#最优时间复杂度:O(n^2)
#最坏时间复杂度:O(n^2)
#辅组空间:O(1)
#稳定性:不稳定
n = len(alist)
for j in range(n-1):
#假定当前值为最小值
min = j
#依次遍历它后面的值,如果比它小就用最小游标指向
for i in range(j+1,n):
if alist[i] < alist[min]:
min = i
#交换当前值与最小值,这样就前有序
alist[min], alist[j] = alist[j], alist[min]
def insert_sort(alist):
'''插入排序'''
#平均情况:O(n^2)
#最优时间复杂度:O(n)
#最坏时间复杂度:O(n^2)
#辅组空间:O(1)
#稳定性:稳定
n = len(alist)
#未有序序列
for j in range(1,n):
#从后往前遍历有序序列+当前位置元素(注意:range不能到0,因为没有alist[0-1])
for i in range(j,0,-1):
#如果当前位置元素小于前一个有序序列的值,就交换
if alist[i] < alist[i-1]:
alist[i], alist[i-1] = alist[i-1], alist[i]
else:
#优化,当前位置大于前一个,直接跳出
break
def shell_sort(alist):
'''希尔排序'''
#平均情况:O(nlogn)~O(n^2)
#最优时间复杂度:O(n^(1.3))
#最坏时间复杂度:O(n^2)
#辅组空间:O(1)
#稳定性:不稳定
#插入排序的升级
n = len(alist)
#步长
temp = n // 2
while temp > 0:
#从temp开始遍历,每个小序列一同开始操作
for i in range(temp,n):
#用一个新值遍历每个小序列
j = i
while j > 0:
if alist[j] < alist[j-temp]:
alist[j], alist[j-temp] = alist[j-temp], alist[j]
j -= temp
else:
break
#缩短步长 //=
temp //= 2
def quick_sort(alist, a_left, a_right):
'''快速排序'''
#平均情况:O(nlogn)
#最优时间复杂度:O(nlogn)
#最坏时间复杂度:O(n^2)
#辅组空间:O(logn)~O(n)
#稳定性:不稳定
if a_left >= a_right:
return
#用temp直接把标志值拿出,不要在后面的代码中用类似alist[a_left],否则会直接替换里面的值
temp = alist[a_left]
left = a_left
right = a_right
#只要左右游标不相遇
while left < right:
#右游标大于标志时,右游标左移
while left < right and alist[right] >= temp:
right -= 1
#到这里肯定右游标小于标志,将右标的值给左标
alist[left] = alist[right]
#左游标小于标志时,左游标右移
while left < right and alist[left] < temp:
left += 1
alist[right] = alist[left]
#相遇时,将标志的值填入这个位置
alist[left] = temp
#分别递归左右区域
quick_sort(alist, a_left, left-1)
quick_sort(alist, left+1, a_right)
#这个有返回值,要接收一下
def merge_sort(alist):
'''归并排序'''
#平均情况:O(nlogn)
#最优时间复杂度:O(nlogn)
#最坏时间复杂度:O(nlogn)
#辅组空间:O(n)
#稳定性:稳定
#一直递归调用,直到长度为一,return
n = len(alist)
if n <=1:
return alist
mid = n // 2
left_list = merge_sort(alist[:mid])
right_list = merge_sort(alist[mid:])
#左右两个列表的游标
left_pointer, right_pointer = 0, 0
result = []
#只要有一个游标遍历完成,结束while,此时必在左右中剩余一个元素
while left_pointer < len(left_list) and right_pointer < len(right_list):
if left_list[left_pointer] <= right_list[right_pointer]:
result.append(left_list[left_pointer])
left_pointer += 1
else:
result.append(right_list[right_pointer])
right_pointer += 1
#将剩下的元素添加进结果集
result += left_list[left_pointer:]
result += right_list[right_pointer:]
return result
if __name__ == '__main__':
alist = [9,8,7,6,5,4,3,2,1]
print(alist)
print(merge_sort(alist))