"""
堆排序:是一種樹形選擇排序方法,特點:
在排序的過程中,將l[1...n]看成是一顆完全二叉樹的順序儲存結構,利用完全二叉樹中雙親結點和孩子結點之間的內在關係,
在當前無序區中選擇關鍵字最大(或最小)的元素。
堆的定義如下:
n個關鍵字序列l[1...n]稱為堆,當且僅當該序列滿足:
1、 l(i) <= l(2i) 滿足此公式的稱為小根堆
2、 l(i) >= l(2i) 滿足此公式的稱為大根堆
(其中1 =< i <= 向下取整 )
顯然,在大根堆中,最大的元素存放在根節點中,且對其任一非根結點,它的值小於或者等於其雙親結點的值。
堆排序的思想(以大根堆為例):
堆排序的關鍵是構造初始堆,對初始序列建堆,就是乙個反覆篩選的過程。
1、首先將待排序的陣列構造出乙個大根堆(自下往上逐步調整為大根堆):
建堆的思路:n個結點完全的二叉樹,最後乙個結點是第個結點的孩子。
對以結點為根的子樹篩選:(大根堆:若根結點的關鍵字小於左右子女中關鍵字較大者則交換),使該子樹成
為堆。之後向前依此對以各結點(n/2-1 ~ 1)為根的子樹進行篩選,看該結點值是否大於其左右子結點的值,若不是,
將左右子結點中較大值與之交換,交換後可能破壞下一級的堆,於是繼續採用上述方法構造下一級的堆,直到以該結點
為根的子樹構成堆為止。
2、取出這個大根堆的堆頂結點(最大值),與堆的最下最右的元素進行交換,把剩下的元素再構造出乙個大根堆
3、重複第二步,直到這個大根堆的長度為1,此時完成排序。
"""# python的collections庫里提供了鍊錶結構deque,我們先使用它初始化乙個無序序列:
from collections import deque
def swap_param(l, i, j):
l[i], l[j] = l[j], l[i]
return l
def heap_adjust(l, start, end):
"""刪除堆頂元素時,先將最後乙個元素與堆頂元素交換,由於此時破壞了堆的性質,需要
對此時根結點進行向下調整操作。
:param l:
:param start:
:param end:
:return:
"""# 對以[n/2]結點為根的子樹篩選,temp 暫存根節點start
temp = l[start]
i = start
j = 2 * i
# 沿著key(關鍵字)較大的子結點向下篩選
while j <= end:
# 保證 j 取到左右子樹中關鍵字較大的值
if (j < end) and (l[j] < l[j + 1]):
j += 1
if temp < l[j]:
l[i] = l[j]
i = j
j = 2 * i
else:
# 篩選結束:temp>=l[j]:說明根結點的關鍵字最大。
break
l[i] = temp
def adjust_up(l, k):
"""對堆進行插入操作,先將新結點放在堆的末端,對新結點執行向上調整。
:param l:
:param k: 向上調整的結點,也為堆的元素個數
:return:
"""temp = l[k]
i = k // 2
while i > 0 and l[i] < l[0]:
l[k] = l[i]
k = i
i = k //2
l[k] = temp
def heap_sort(l):
"""因為引入了乙個輔助空間,所以使l_length = len(l) - 1
第乙個迴圈做的事情是把序列調整為乙個大根堆(heap_adjust函式)
第二個迴圈是把堆頂元素和堆末尾的元素交換(swap_param函式),然後把剩下的元素調整為乙個大根堆(heap_adjust函式)
:param l:
:return:
"""l_length = len(l) - 1
first_sort_count = l_length // 2
# 從i = [n/2]-1 ,反覆調整堆
for i in range(first_sort_count):
heap_adjust(l, first_sort_count - i, l_length)
for i in range(l_length - 1):
l = swap_param(l, 1, l_length - i)
heap_adjust(l, 1, l_length - i - 1)
return [l[i] for i in range(1, len(l))]
if __name__ == '__main__':
l = deque([50, 16, 30, 10, 60, 90, 2, 80, 70])
print(heap_sort(l))
Fighting 演算法 基數排序
基數排序 基數排序是一種很特別的排序方法,它不是基於比較進行排序的演算法,而是多關鍵字排序思想。借助 分配 和 收集 兩種操作,對單邏輯關鍵字進行排序。基數排序又分為最高位優先 msd 排序和最低位優先 lsd 排序。msd 先從高位開始進行排序,對每個關鍵字,可採用計數排序 lsd 先從低位開始進...
Fighting 演算法 簡單選擇排序
選擇排序的基本思想 給定序列 l 1,2,3,i,i 1,n 1,n 每一趟 例如地i趟 在後面n i 1 i 1,2,n 1 個待排序的元素中,選取關鍵字最小的元素,做為有序子串行的第i個元素,直到第n 1趟排完,待排序元素只剩下乙個時結束。簡單選擇排序思想 假設排序表為l 1.n 第i趟排序即從...
排序演算法 堆排序
1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...