Fighting 演算法 堆排序

2021-09-11 04:34:38 字數 2555 閱讀 6508

"""

堆排序:是一種樹形選擇排序方法,特點:

在排序的過程中,將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 堆...