算法原理及其比較
算法基本思想(假設原始序列爲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]