** 先贴代码,下面再开始比较 **
冒泡排序:
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)
# 最坏情况下,时间复杂度为O(n^2)
# 稳定性:稳定
"""
注意第8行代码
与选择排序不同,它交换的是数组元素。
"""
选择排序:
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[j], alist[min_index] = alist[min_index], alist[j]
# 时间复杂度为O(n^2)
# 稳定性:不稳定
"""
注意第8行代码
与冒泡排序不同,它交换的是索引。
"""
插入排序:
def insert_sort(alist):
"""插入排序"""
n = len(alist)
# 从第二个位置,即下标为1的元素开始,向前插入
for j in range(1, n):
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
# # 第二种写法
# # 代表内层循环的起始值
# i = j
# # 从右边的无序序列中取出第一个元素,插入到前面的有序序列中合适的位置
# while i > 0:
# if alist[i] < alist[i-1]: # 改变小于号可变为降序排序
# alist[i], alist[i-1] = alist[i-1], alist[i]
# i -= 1
# else:
# break
# 最优时间复杂度:O(n) ,即原序列已处于有序状态(例如原升序序列按升序排列)
# 最坏时间复杂度:O(n^2)
# 稳定性:稳定
比较:
三者的循环条件比较:
- 冒泡:
for j in range(0, n-1); for i in range(1, n-1-j)
- 选择:
for j in range(0, n-1); for i in range(j+1, n)
- 插入:
for j in range(1, n); for i in range(j, 0, -1)
解释(注意python的range函数取值范围,要头不要尾):
- 冒泡:外层循环(游标)从0到n-2,即倒数第二个元素;内层循环用于元素比较。从整个序列在排序过程中的变化来看,左边的查找区逐渐缩短,右边的有序子序列逐渐增长(所以内循环的终止位置在n-1-j)。
- 选择:外层循环(游标)从0到n-2,即倒数第二个元素;内层循环用于元素比较。从整个序列在排序过程中的变化来看,左边的有序子序列逐渐增长,右边的查找区逐渐缩短。
- 插入:外层循环(游标)从1到n-1,即倒数第一个元素;内层循环用于元素比较。从整个序列在排序过程中的变化来看,左边的有序子序列逐渐增长,右边的查找区逐渐缩短。
----- | 冒泡排序 | 选择排序 | 插入排序 |
---|---|---|---|
时间复杂度 | O(n),O(n^2) | O(n^2) | O(n),O(n^2) |
稳定性 | 稳定 | 不稳定 | 稳定 |
其它方面的比较:
- 冒泡和插入排序调换的都是元素本身,选择排序调换的是索引。
- 冒泡和插入排序都是相邻元素相互比较,选择排序用假定的最小值去和后面的所有元素比较。
- 冒泡没有假设条件,选择排序假设第一个元素最小,插入排序假设第一个元素为有序序列。
- 冒泡和插入排序在对比查找的时候可以中途结束本次循环,选择排序不行。