Python实现多种排序方式
冒泡排序
- 概述与原理
冒泡排序(Bubble Sort)是一种基础排序算法;
冒泡排序会依次比较列表中两个相邻的元素,根据排序方式进行置换相邻元素的顺序,
以达到一轮比较后使最大或最小的元素排到列表的开头,形似"冒泡",n轮比较后达到顺序列表; - 代码实现(升序)
def bubble_sort(demo):
for i in range(1, len(demo)):
# i表示冒泡的轮数
for j in range(0,len(demo)-i):
# j表示每次比较的元素索引
if demo[j]>demo[j+1]:
# 当索引小的元素大于索引大的元素时进行交换
demo[j],demo[j+1] = demo[j+1],demo[j]
print(demo)
test_list = [0,9,2,5,3,6,1]
bubble_sort(test_list)
[0, 1, 2, 3, 5, 6, 9] # 输出顺序列表
- 稳定性与时间复杂度
- 稳定性
当待排序列表中存在相等元素时排序过程不会交换相等的元素,故冒泡排序属于稳定排序方式; - 时间复杂度
对于排序最坏的情况是待排序列表完全逆序,此时需要进行n-1
轮排序,每一轮需要进行n-i
次交换操作,即每轮平均交换次数n/2
,则时间复杂度为 T(n)=n(n-1)/2,所以冒泡排序的时间复杂度为 O(n^2);
选择排序
- 概述与原理
选择排序(Selection Sort)是一种基础排序算法;
选择排序会在未排序的列表中找到最大或最小的元素,将其存放到列表的起始位置,
然后依次在剩余未排序的列表中选择最大或最小的元素,放到剩余列表的起始位置,直到完全排序; - 代码实现(升序)
def select_sort(demo):
for i in range(len(demo)-1):
# i表示需要选择的轮数
min_index = i
# min_index表示筛选出最小元素的索引
for j in range(i+1,len(demo)):
# j表示每次进行比较的元素索引
if demo[j]<demo[min_index]:
# 当待比较元素j比已知最小元素小时最小元素的索引更新为j
min_index = j
if min_index != i:
# 经过一轮比较后如果最小元素索引发生改变,则使最小元素与起始位置元素进行交换
demo[i],demo[min_index] = demo[min_index],demo[i]
print(demo)
test_list = [0,9,2,5,3,6,1]
select_sort(test_list)
[0, 1, 2, 3, 5, 6, 9] # 输出顺序列表
- 稳定性与时间复杂度
- 稳定性
当待排序列表中存在相等元素时排序过程会交换相等的元素,如列表[5(0),5(1),1],做一轮选择排序后变为[1,5(1),5(0)],故选择排序属于不稳定排序方式; - 时间复杂度
选择排序需要进行n-1
轮排序,每一轮需要进行n-i
次交换操作,即每轮平均交换次数n/2
,则时间复杂度为 T(n)=n(n-1)/2,所以选择排序的时间复杂度为 O(n^2);
插入排序
- 概述与原理
插入排序(Insert Sort)是一种基础排序算法;
插入排序会选择未排序列表中的第一个元素依次与已排序的列表元素进行比较,根据排序方式进行置换,直到该元素插入合适的位置,即融入已排序列表;
然后依次在剩余未排序的列表中第一个元素做插入,最后所有元素完成排序; - 代码实现(升序)
def insert_sort(demo):
for i in range(1,len(demo)):
# i表示需执行插入的轮数
for j in range(i,0,-1):
# j表示需要进行比较的元素索引,从已排序列表的后方开始比较
if demo[j]<demo[j-1]:
demo[j],demo[j-1] = demo[j-1],demo[j]
else:
break
print(demo)
print(demo)
test_list = [0,9,2,5,3,6,1]
insert_sort(test_list)
[0, 1, 2, 3, 5, 6, 9] # 输出顺序列表
- 稳定性与时间复杂度
- 稳定性
当待排序列表中存在相等元素时排序过程会交换相等的元素,如列表[5’,5,1],做一轮选择排序后变为[1,5,5’],故选择排序属于不稳定排序方式; - 时间复杂度
选择排序需要进行n-1
轮排序,每一轮需要进行n-i
次交换操作,即每轮平均交换次数n/2
,则时间复杂度为 T(n)=n(n-1)/2,所以选择排序的时间复杂度为 O(n^2);
快速排序
- 概述与原理
快速排序(Quick Sort)是对冒泡排序算法的一种改进。
首先在无序列表中选择一个元素定为基值元素,通过一轮排序将待排序的列表分成两部分,
一部分中所有数据比基值元素小,另一部分中所有数据比基值大,
再通过递归思想对这两部分未排序的列表分别进行快速排序,最后达到整个列表有序排列; - 代码实现(升序)
def quick_sort(demo):
if len(demo) > 1:
# 当列表长度大于1时进行排序
mid = demo[len(demo) // 2]
# 选取基准元素,此例选取中间值作为基准元素
left, right = [], []
# 初始化基准元素左右两侧为空列表
demo.remove(mid)
# 将基准元素从原列表中移除
for i in demo:
# 依次遍历列表元素,小于基准元素的值放到left列表中,大于基准元素的值放到right列表中
left.append(i) if i < mid else right.append(i)
return quick_sort(left) + [mid] + quick_sort(right)
# 返回排序后的列表
else:
return demo
# 递归结束条件为待排序列表仅有一个元素
test_list = [0,9,2,5,3,6,1]
test_list = quick_sort(test_list)
print(test_list)
[0, 1, 2, 3, 5, 6, 9] # 输出顺序列表
- 稳定性与时间复杂度
- 稳定性
当待排序列表中存在相等元素时排序过程会交换相等的元素,如列表[6,5’,5,1,7],基准值选5,选择排序后变为[1,5,5’,6,7],故快速排序属于不稳定排序方式; - 时间复杂度
快速排序中一次排序仅能正确排一个元素,每轮排序平均交换次数n/2
,则时间复杂度为 T(n)=n(n-1)/2,所以快速排序的时间复杂度为 O(n^2);