排序算法的稳定性
冒泡排序
比选择排序更稳定
def bubble_sort(alist):
"""冒泡排序"""
n = len(alist)
for j in range(0, n-1):
# 注意这里,到n-2截止所以最后一个应是n-1
# 而冒泡排序
for i in range(0, n-1-j):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
bubble_sort(li) # 调用方法的时候直接写即可
print(li)
或者
def bubble_sort(alist):
"""冒泡排序"""
n = len(alist)
for j in range(len(alist)-1, 0, 1): # j范围表示方法变动
# 注意这里,到n-2截止所以最后一个应是n-1
# 而冒泡排序
for i in range(0, n-1-j):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
bubble_sort(li) # 调用方法的时候直接写即可
print(li)
此时算法复杂度为o(n^2)
改进:考虑如果一开始就是有序数列不需要排序,则可以这样
def bubble_sort(alist):
"""冒泡排序"""
n = len(alist)
for j in range(0, n-1):
count = 0 # “班长”从头到尾走一遍,如果直接可行即退出
for i in range(0, 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
改进后最坏时间复杂度没变,最优时间复杂度变为o(n)
选择排序
def select_sort(alist):
n = len(alist)
for j in range(0, n-1):
min_index = j
for i in range(j+1, n):
if alist[min_index] > alist[i]:
min_index = i
alist[min_index], alist[j] = alist[j], alist[min_index]
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
select_sort(li)
print(li)
或者
def select_sort(alist):
n = len(alist)
for j in range(0, n-1):
min_index = j
for i in range(j+1, n):
if alist[min_index] > alist[i]:
# min_index = i
alist[i], alist[j] = alist[j], alist[i]
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
select_sort(li)
print(li)
插入排序
注意:插入排序前面已排好的数列是有序的,后续排列过程中,某数alist[i]在找到比它小的数alist[i-1]时,该数的插入排序即完成。
def insert_sort(alist):
"""插入排序"""
n = len(alist)
for i in range(1, n):
# 从右边的无序序列中取出一个元素,从小到大插入到相应位置
while i > 0:
if alist[i-1] > alist[i]:
alist[i], alist[i-1] = alist[i-1], alist[i]
i -= 1 # 因为前面数列已是有序数列,所以
else:
break # 检测到某alist[1-1]<alist[i]之后即可停止
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
insert_sort(li)
print(li)
时间复杂度:o(n^2)
希尔排序
gap表示一个间隔,前gap个数的顺序不用特意考虑。
gap需要分别取len(alist)折半取整、再折半取整……1,多次执行希尔排序
def shell_sort(alist):
"""希尔排序"""
n = len(alist)
gap = n//2
while gap > 0:
for i in range(gap, n):
# 从右边的无序序列中取出一个元素,从小到大插入到相应位置
while i > 0:
if alist[i-gap] > alist[i]:
alist[i], alist[i-gap] = alist[i-gap], alist[i]
i -= gap # 因为前面数列已是有序数列,所以
else:
break
gap //= 2
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
shell_sort(li)
print(li)
最坏时间复杂度因gap取值不同而不同
时间复杂度:o(n^2)
稳定性:不稳定
快速排序
def quick_sort(alist, first, last):
"""快速排序"""
if first >= last:
return
mid_value = alist[first]
low = first
high = last
while low < high:
while low < high and alist[high] >= mid_value: # 当存在多个与mid相等的值时统一放到mid的一边
high -= 1
alist[low] = alist[high] # 若遇到一个比mid小的alist[high]则放到low上
# low += 1
while low<high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
# high += 1
# 从循环退出时low == high
alist[low] = mid_value
# 这时分割成出去low索引处元素的从头开始的alist[:low-1]和直到最后的alist[low+1:]
# 可以执行递归嵌套
# 注意不要用新的列表,要在原列表上排序quick_sort(alist[:low-1])
# quick_sort(alist[low+1:])
# 对low左边的列表执行排序
quick_sort(alist, first, low-1)
# 对low右边的列表执行排序
quick_sort(alist, low+1, last)
if __name__ == "__main__":
li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(li)
quick_sort(li, 0, len(li)-1)
print(li)
最优时间复杂度o(nlogn)
最坏时间复杂度o(n^2)
稳定性:不稳定
归并排序
二分查找
只能作用在***有序***顺序表上(已排序完成的有序列表)
递归版本:
def binary_search(alist, item):
"""二分查找递归"""
n = len(alist)
if n > 0:
mid = n//2
if item == alist[mid]:
return True
elif item < alist[mid]:
return binary_search(alist[:mid], item)
else:
return binary_search(alist[mid+1:], item)
return False
if __name__ == "__main__":
li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
print(binary_search(li, 100))
print(binary_search(li, 54))
非递归版本:
def binary_search(alist, item):
"""二分查找非递归"""
n = len(alist)
first = 0
last = n-1
while first <= last:
mid = (first + last)//2
if alist[mid] == item:
return True
elif item < alist[mid]:
last = mid - 1
else:
first = mid + 1
return False
if __name__ == "__main__":
li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
print(binary_search(li, 100))
print(binary_search(li, 54))