算法原理及其比较
算法基本思想(假设原始序列为L,长度为n):
- 冒泡排序:每次从序列L中选出最大元素,放到序列末尾,也即L[n]的位置,然后对剩下的序列(L[0:n-1])重复该步骤;
- 插入排序:原始序列分为已排序、未排序两个序列,每次从未排序序列中取第一个元素,插入已排序序列中;
- 选择排序:原始序列分为已排序、未排序两个序列,每次从未排序序列中选出最小元素,放入已排序序列末尾;
三种排序算法的比较:
- 就空间复杂度而言,三者都是原地排序算法,空间复杂度都是;
- 就时间复杂度而言,平均时间复杂度、最坏情况时间复杂度都是,最好情况下,也即序列已经有序的情况下,冒泡和插入算法的时间复杂度为,而选择排序的时间复杂度仍然为;
- 就算法的稳定性而言,冒泡和插入均是稳定的排序算法,而选择属于不稳定的排序算法;
Python实现代码:
import copy
def bubbleSort(L, n):
""" 冒泡排序:每次选出最大元素放在末尾
L: 待排序列表;
n: 列表长度;
"""
for i in range(n):
flag = False
for j in range(n-i-1):
if L[j]>L[j+1]:
temp = L[j]
L[j] = L[j+1]
L[j+1] = temp
flag = True
if flag == False:
break
print(L[:n-i-1],"|", L[n-i-1:])
return L
def insertSort(L,n):
""" 插入排序:每次从未排序区选一个值插入已排序区
L: 待排序列表;
n: 列表长度;
"""
for i in range(1,n):
print(L[:i],"|", L[i:])
value = L[i]
# j的范围是从i-1到-1,这样做的目的是:当j比较到0位置时会有两种情况(移动元素、不移动元素),
# 使j最小至-1可以不必特殊处理这种情况。
for j in range(i-1,-2,-1):
if j == -1:
break
if value<L[j]:
L[j+1] = L[j]
else:
break
L[j+1] = value
return L
def selectSort(L,n):
""" 选择排序:每次从未排序区选出最小元素,放在已排序区末尾
L: 待排序列表;
n: 列表长度;
"""
for i in range(n):
print(L[:i],"|", L[i:])
minimum = L[i]
min_idx = i
for j in range(i,n):
if minimum > L[j]:
minimum = L[j]
min_idx = j
if min_idx != i:
temp = L[i]
L[i] = minimum
L[min_idx] = temp
return L
if __name__ == "__main__":
L = [6,5,4,3,2,1,0]
n = len(L)
print("\n冒泡排序过程:")
print(bubbleSort(copy.deepcopy(L),n))
print("\n插入排序过程:")
print(insertSort(copy.deepcopy(L),n))
print("\n选择排序过程:")
print(selectSort(copy.deepcopy(L),n))
输出结果:
冒泡排序过程:
[5, 4, 3, 2, 1, 0] | [6]
[4, 3, 2, 1, 0] | [5, 6]
[3, 2, 1, 0] | [4, 5, 6]
[2, 1, 0] | [3, 4, 5, 6]
[1, 0] | [2, 3, 4, 5, 6]
[0] | [1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5, 6]
插入排序过程:
[6] | [5, 4, 3, 2, 1, 0]
[5, 6] | [4, 3, 2, 1, 0]
[4, 5, 6] | [3, 2, 1, 0]
[3, 4, 5, 6] | [2, 1, 0]
[2, 3, 4, 5, 6] | [1, 0]
[1, 2, 3, 4, 5, 6] | [0]
[0, 1, 2, 3, 4, 5, 6]
选择排序过程:
[] | [6, 5, 4, 3, 2, 1, 0]
[0] | [5, 4, 3, 2, 1, 6]
[0, 1] | [4, 3, 2, 5, 6]
[0, 1, 2] | [3, 4, 5, 6]
[0, 1, 2, 3] | [4, 5, 6]
[0, 1, 2, 3, 4] | [5, 6]
[0, 1, 2, 3, 4, 5] | [6]
[0, 1, 2, 3, 4, 5, 6]