一、快速排序算法
快速排序(Quicksort)是對冒泡排序的一種改進。
原理:快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據,都比,另外一部分的所有數據,都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
設要排序的數組是A[0]……A[N-1],首先任意選取一個數據(通常選用數組的第一個數)作爲關鍵數據,然後將所有比它小的數都放到它左邊,所有比它大的數都放到它右邊,這個過程稱爲一趟快速排序。值得注意的是,快速排序不是一種穩定的排序算法,也就是說,多個相同的值的相對位置也許會在算法結束時產生變動。
一趟快速排序的算法是:
- 1)設置兩個變量i、j,排序開始的時候:i=0,j=N-1;
- 2)以第一個數組元素作爲關鍵數據,賦值給key,即key=A[0];
- 3)從j開始向前搜索,即由後開始向前搜索(j–),找到第一個小於key的值A[j],將A[j]和A[i]的值交換;
- 4)從i開始向後搜索,即由前開始向後搜索(i++),找到第一個大於key的A[i],將A[i]和A[j]的值交換;
- 5)重複第3、4步,直到i=j;(3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到爲止。找到符合條件的值,進行交換的時候i,j指針位置不變。另外,i==j這一過程一定正好是i+或j-完成的時候,此時令循環結束)。
data = [45,3,2,6,3,78,5,44,22,65,46]
def quickSort(data, start, end):
i = start
j = end
# i與j重合時,一次排序結束
if i >= j:
return
# 設置最左邊的數爲基準值
flag = data[start]
while i < j:
while i<j and data[j] >= flag:
j -= 1
# 找到右邊第一個小於基準的數,賦值給左邊i。此時左邊i被記錄在flag中
data[i] = data[j]
while i<j and data[i] <= flag:
i += 1
# 找到左邊第一個大於基準的數,賦值給右邊的j。右邊的j的值和上面左邊的i的值相同
data[j] = data[i]
# 由於循環以i結尾,循環完畢後把flag值放到i所在位置。
data[i] = flag
# 除去i之外兩段遞歸
quickSort(data, start, i-1)
quickSort(data, i+1, end)
quickSort(data,0, len(data)-1)
print data
二、堆排序算法(參考)
原理:堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。這個過程其實就是先構建一個最大/最小二叉堆,然後不停的取出最大/最小元素(頭結點),插入到新的隊列中,以此達到排序的目的。如下圖所示。
堆(二叉堆):可以視爲一棵完全的二叉樹,完全二叉樹的一個“優秀”的性質是,除了最底層之外,每一層都是滿的,這使得堆可以利用數組來表示(普通的一般的二叉樹通常用鏈表作爲基本容器表示),每一個結點對應數組中的一個元素。
def big_endian(arr, start, end):
root = start
while True:
child = root * 2 + 1 # 左孩子
if child > end: # 孩子比最後一個節點還大 也就意味着最後一個葉子節點了 就得跳出去一次循環已經調整完畢
break
if child + 1 <= end and arr[child] < arr[child + 1]: # 爲了始終讓其跟子元素的較大值比較 如果右邊大就左換右,左邊大的話就默認
child += 1
if arr[root] < arr[child]: # 父節點小於子節點直接換位置 同時座標也得換這樣下次循環可以準確判斷是否爲最底層是不是調整完畢
arr[root], arr[child] = arr[child], arr[root]
root = child
else: # 父子節點順序正常 直接過
break
def heap_sort(arr):
# 無序區大根堆排序
first = len(arr) // 2 - 1
for start in range(first, -1, -1): # 從下到上,從右到左對每個節點進調整 循環得到非葉子節點
big_endian(arr, start, len(arr) - 1) # 去調整所有的節點
for end in range(len(arr) - 1, 0, -1):
arr[0], arr[end] = arr[end], arr[0] # 頂部尾部互換位置
big_endian(arr, 0, end - 1) # 重新調整子節點的順序 從頂開始調整
return arr
def main():
l = [3, 1, 4, 9, 6, 7, 5, 8, 2, 10]
print(heap_sort(l)) # 原地排序
if __name__ == "__main__":
main()