文章出处:
https://blog.csdn.net/qq_35955528/article/details/98344262
1、冒泡排序
工作原理:
- 比较相邻两个元素,如果第一个元素比第二个元素大(升序),则将这两个元素交换;
- 对每一对相邻的元素做同样的工作,从开始第一对到结尾最后一对。做完一次之后,最后一个元素就是最大的元素;
- 针对所有元素作上述操作,除最后一个元素外;
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
def bullet_sort(aList):
n = len(aList)
for j in range(n -1, 0, -1):
for i in range(j):
if aList[i] > aList[i + 1]:
aList[i], aList[i + 1] = aList[i + 1], aList[i]
if __name__ == '__main__':
a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(a)
bullet_sort(a)
print(a)
时间复杂度
- 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
- 最坏时间复杂度:O(n2)
- 稳定性:稳定(当两个属性相等时,不会更改原有顺序)
图例
2、选择排序
工作原理:
- 查找最小的元素,放在起始位置;
- 在未排序的序列中再找出最小元素,放在已排序序列的末尾;
- 针对剩下元素上述操作,直到末尾截止。
def select_sort(aList):
n = len(aList)
for j in range(n - 1):
min_index = j
for i in range(j + 1, n):
if aList[i] < aList[min_index]:
min_index = i
if min_index != j:
aList[j], aList[min_index] = aList[min_index], aList[j]
if __name__ == '__main__':
a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(a)
select_sort(a)
print(a)
时间复杂度
- 最优时间复杂度:O(n2)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定(考虑升序每次选择最大的情况)
图例
3、插入排序
工作原理:
- 从第二个元素开始,与前面的元素比较;
- 未排序的元素在已排序的序列中从后往前扫描,插入到对应位置;
- 重复上述操作,直至到最后一个元素插入成功。
def insert_sort(aList):
n = len(aList)
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]
if __name__ == '__main__':
a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(a)
insert_sort(a)
print(a)
时间复杂度
- 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
- 最坏时间复杂度:O(n2)
- 稳定性:稳定
图例
4、快速排序
工作原理:
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
def quick_sort(aList, start, end):
if start >= end:
return
mid = aList[start]
low = start
high = end
while low < high:
# 从右往左遍历,查找比基准元素小的元素
while low < high and aList[high] >= mid:
high -= 1
aList[low] = aList[high]
# 从左往右遍历,查找比基准元素大的元素
while low < high and aList[low] < mid:
low += 1
aList[high] = aList[low]
aList[low] = mid
quick_sort(aList, start, low - 1)
quick_sort(aList, low + 1, end)
if __name__ == '__main__':
a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(a)
quick_sort(a, 0, len(a) - 1)
print(a)
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定
图例
5、希尔排序
工作原理:
- 将序列按照步长进行分组
- 将分组后的元素进行插入排序;
- 缩短步长,继续执行上述操作;
- 直到步长为0时结束。
def shell_sort(aList):
n = len(aList)
gap = n // 2
while gap > 0:
for j in range(gap, n):
i = j
while i >= gap and aList[i] < aList[i - gap]:
aList[i], aList[i - gap] = aList[i - gap], aList[i]
i -= gap
gap = gap // 2
if __name__ == '__main__':
a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(a)
shell_sort(a)
print(a)
时间复杂度
- 最优时间复杂度:根据步长序列的不同而不同
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定
图例
6、归并排序
工作原理:
- 将序列进行拆分;
- 将拆分后的序列进行两两排序合并;
- 将有序序列再进行两两排序合并;
- 直至合并成一条序列。
def merge_sort(aList):
n = len(aList)
if n <= 1:
return aList
num = n // 2
# 拆分
left_list = merge_sort(aList[:num])
right_list = merge_sort(aList[num:])
# 合并
left, right = 0, 0
result = []
while left < len(left_list) and right < len(right_list):
if left_list[left] <= right_list[right]:
result.append(left_list[left])
left += 1
else:
result.append(right_list[right])
right += 1
result += left_list[left:]
result += right_list[right:]
return result
if __name__ == '__main__':
a = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(a)
b = merge_sort(a)
print(b)
时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度:O(nlogn)
- 稳定性:稳定