1. 冒泡排序:
- 原理
冒泡排序算法的基本原理就是比較相鄰兩個數字的大小。將兩個數中比較大的那個數交換到靠後的位置,不斷交換下去就可以將最大的那兩個數放到隊列的尾部。然後重頭再次交換)(交換list.lenght-1次),直到將數列排成有序數列。
- 代碼實現
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def bubbleSort(List):
"""
冒泡排序
:param List:
:return:
"""
if len(List) <= 1:
return List
for i in range(len(List)-1): # 經過n-1輪排序
for j in range(len(List)-1): # 比較前一個數和後一個數的大小關係
if List[j] >= List[j+1]:
List[j], List[j+1] = List[j+1], List[j] # 如果前一個數比後一個數大,則調換位置
return List
if __name__ == '__main__':
print(List)
print(bubbleSort(List))
runtime = timeit.timeit("bubbleSort(List)","from __main__ import bubbleSort, List",number=1000)
print(runtime)
2. 選擇排序:
- 原理
簡單來說,選擇排序只做了一件事件,那就是從數列中選擇最大(最小)的那個數,將這個數放到合適的位置。然後拋開這個數的子序列中找最大(最小)的那個數放到合適的位置。然後一直到子序列爲空。
- 代碼實現
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
"""
# 這個雖簡潔易懂,但有重複數字會有有Bug,原因爲相同數下標無法確定
def selectSort(List):
if len(List) <= 1: # 如果長度小於等於1,直接返回
return List
for i in range(0, len(List)-1): # 遍歷數組
if List[i] >= min(List[i+1:]): # 如果對應下標數的值大於剩餘部分的最小值,交換位置
minIndex = List.index(min(List[i+1:])) # 求剩餘部分的最小值小標
List[i], List[minIndex] = List[minIndex], List[i] #滿足條件, 交換位置
return List
"""
def selectSort(List):
if len(List) <= 1: # 如果長度小於等於1,直接返回
return List
for i in range(len(List)-1):
min_index = i
for j in range(i+1,len(List)):
if List[j] < List[min_index]:
min_index = j
List[i], List[min_index] = List[min_index], List[i]
return List
if __name__ == '__main__':
print(List)
print(selectSort(List))
print(timeit('selectSort(List)','from __main__ import selectSort, List',number=1000))
3. 插入排序:
- 原理
插入排序首先將數列分爲兩部分,數列的第一數爲left,其餘數位right部分。然後將right部分中的數逐一取出,插入到left部分的適當位置。當right部分爲空時,left部分就成了一個有序的序列。
- 代碼實現
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def insertSort(List):
if len(List) <= 1:
return List
for right in range(1,len(List)): # 遍歷右邊沒有排序的數組
target = List[right] # 需要排序的值
for left in range(0, right):
if target <= List[left]:
List[left+1:right+1] = List[left:right] # 將左邊已經排序好的數組整體右移一位
List[left] = target # 將需排序的值到左邊已排序好數組的適當位置
break # 提高性能,如果比邊已排序好的最小數都小,一次則跳出循環
return List
# 第二種思路,從左邊排序的列表最後邊向最左邊比較
def insertSort2(List):
if len(List) <= 1:
return List
for i in range(1,len(List)):
j = i
while j > 0:
if List[j] < List[j-1]:
List[j], List[j-1] = List[j-1], List[j]
j -= 1
else:
break
return List
if __name__ == '__main__':
print(List)
print(insertSort(List))
print(timeit('insertSort(List)','from __main__ import insertSort, List',number=1000))
4. 快速排序:
- 原理
以列表中任意一個數爲基準(一般選用列表的第一個數,因爲遞歸調用的最後每個列表只有一個數),將列表分爲左右兩個子列表:左邊子列表的數要比基準數小,右邊子序列表的數要比基準數打。然後繼續把左邊子列表和右邊子列表按照同樣的方法繼續分解、比較,一直到無法分解爲止。然後按照左邊子列表(比基準數小) + 基準數 + 右邊子列表(比基準數大)的方式連接起來。最後合成了一個有序數列。
- 代碼實現
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def quickSort(List):
"""
快速排序:優點:代碼簡潔,易於理解 缺點: 太過耗費空間
:param List:
:return:
"""
if len(List) <= 1:
return List
left = [] # 左區,用來存放比基準數小的數
right = [] # 右區,用來存放比基準數大的數
for i in List[1:]: # 遍歷除基準數以外的所有數
if i <= List[0]:
left.append(i)
else:
right.append(i)
return quickSort(left) + [List[0]] + quickSort(right) # 遞歸調用,無限拆分後合併各個有序數組
if __name__ == '__main__':
print(List)
print(quickSort(List))
print(timeit('quickSort(List)','from __main__ import quickSort, List',number=1000))
5. 哈希排序
- 原理
改進了得插入排序,將待排序的數組根據差量分成若干的的子數組,分別進行插入排序,通過不斷地修改組距,使得分組數逐漸減少,當組距爲1是,則就是一個插入排序
- 代碼實現
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def shellSort(List):
"""
希爾排序
:param List:
:return:
"""
n = len(List)
gap = n // 2
# gap變化到0之前,插入算法執行的次數
while gap > 0:
# 插入算法,與普通的插入算法的區別就是gap步長
for i in range(gap, n): # 外層循環控制的是所有子序列的所有元素(不包括每一組第一個數)
j = i
while j > 0:
if List[j] < List[j - gap]: # 內層循環就是一個插入排序,比較與前一個數的大小關係
List[j], List[j - gap] = List[j - gap], List[j]
j -= gap
else:
break
# 縮短gap步長
gap //= 2
return List
if __name__ == '__main__':
print(List)
print(shellSort(List))
print(timeit('shellSort(List)','from __main__ import shellSort, List',number=1000))
6. 計數排序
- 原理
計數排序算法採用了一個巧妙的辦法,首先需要創建一個與原數列等長的新數列,選擇一個數爲計基數,然後統計整個數列中有多少個數比基數小。如果有n個數比基數小,那麼將基礎放到數列的n+1位置上(不過此方法的空間和時間複雜度都比較大)
- 代碼實現
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit
List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
def countingSort(List):
"""
計數排序
:param List:
:return:
"""
if len(List) <= 1:
return List
# 創建一個跟原數組長度相同的空數組
rLen = len(List)
rList = [None]*rLen
for i in range(rLen): # 遍歷數組,選擇基數
small = 0 # 記錄比基數小的個數
same = 0 # 記錄跟基數相等的個數
for j in range(rLen): # 找出比基數小或相等的數
if List[j] < List[i]:
small += 1
elif List[j] == List[i]:
same += 1
for k in range(small,small+same):
rList[k] = List[i]
return rList
if __name__ == '__main__':
print(List)
print(countingSort(List))
print(timeit('countingSort(List)','from __main__ import countingSort, List',number=1000))