八大排序算法的python實現(五)堆排序


代碼

#coding:utf-8
#author:徐卜靈
# 堆排序適用於記錄數很多的情況
#與快速排序,歸並排序 時間復雜一樣都是n*log(n)


####################################################
####################################################
####################################################

# from collections import deque
#
# # 這里需要說明元素的存儲必須要從1開始
# # 涉及到左右節點的定位,和堆排序開始調整節點的定位
# # 在下標0處插入0,它不參與排序
# L = deque([49,38,65,97,76,13,27,49])
# L.appendleft(0)
#
# #L = [0,49,38,65,97,76,13,27,49]
#
# def element_exchange(numbers,low,high):
#
#     temp = numbers[low]
#
#     # j 是low的左孩子節點(cheer!)
#     i = low
#     j = 2*i
#
#     while j<=high:
#         # 如果右節點較大,則把j指向右節點
#         if j<high and numbers[j]<numbers[j+1]:
#             j = j+1
#         if temp<numbers[j]:
#             # 將numbers[j]調整到雙親節點的位置上
#             numbers[i] = numbers[j]
#             i = j
#             j = 2*i
#         else:
#             break
#     # 被調整節點放入最終位置
#     numbers[i] = temp
#
# def top_heap_sort(numbers):
#
#     length = len(numbers)-1
#
#     # 指定第一個進行調整的元素的下標
#     # 它即該無序序列完全二叉樹的第一個非葉子節點
#     # 它之前的元素均要進行調整
#     # cheer up!
#     first_exchange_element = length/2
#
#     #建立初始堆
#     print first_exchange_element
#     for x in range(first_exchange_element):
#         element_exchange(numbers,first_exchange_element-x,length)
#
#     # 將根節點放到最終位置,剩余無序序列繼續堆排序
#     # length-1 次循環完成堆排序
#     for y in range(length-1):
#         temp = numbers[1]
#         numbers[1] = numbers[length-y]
#         numbers[length-y] = temp
#         element_exchange(numbers,1,length-y-1)
#
# if __name__=='__main__':
#     top_heap_sort(L)
#     LL = []
#     for x in range(1,len(L)):
#         # print L[x],
#         LL.append(L[x])
#     print LL
##############################################
##############################################
##############################################
def build_maxheap(L,len):
    for i in range(len/2,0,-1):
        # print i
        adjustdown(L,i,len)
    return L

def adjustdown(L,low,high):  #這里只是把一個位於low位置上的數向下移動。
    temp = L[low]
    i = low
    j = 2 * i
    while j <= high:
        # if j <= high and L[j] < L[j+1]:#z這里的L[j+1]可能不存在,所有會有out of index 報錯.
        #     j+=1
        if j <= high and j + 1 <= high:
            if L[j] < L[j+1]:
                j+=1
        if L[j]>temp:
            L[i] = L[j]
            i = j
            j = 2 * i
        else:
            break
    L[i] = temp
    # return L  #由於這里是中間列表,不要輸出。
    # print L
# L = [0,49,38,65,97,76,13,67,47]
# L =  build_maxheap(L,8)
# del L[0]
# # print type(L)
# print "大根堆第一次:",L

len = len(L)-1
def Heap_sort(L,len):
    build_maxheap(L,len)
    for i in range(len,1,-1):
        L[i],L[1] = L[1],L[i]
        # print i
        # print L[len],L[1]
        adjustdown(L,1,i-1)
    return L
L = [49,38,65,97,76,13,67,47]
print "原列表:" ,L
L.insert(0,0)
L = Heap_sort(L,len)
del L[0]
print "堆排序:",L

#基本思路是:
# 1先從后到前進行小數下移的操作。這個后是指len(L)/2
#2.第一步完成后,最大的那個數就上移到了根節點。把這個根節點與最后一個元素交換位置,這時最后一個元素就在有序區里。則只需要將第一個元素再進行下移操作即可。
#3.循環第二步,直到只剩下根節點。

堆排序真的是排序算法中我花費時間最多的算法了,最開始是理解原理上出了問題。理解了之后寫代碼又出了問題。

對於二叉樹不是很熟的最好復習一下樹的知識。

理解了之后就能很好的寫代碼了。

思路:

1.從len(L)/2 到1開始,建立大根堆。這里需要注意的是:這里的元素並不是一次就能移動到最終的位置的。只有迭代到第一個元素,才能建立一個大根堆。

2.將堆頂元素與無序區最后一個元素交換位置,破壞了大根堆,則重新建立大根堆。

3.迭代第二步,直到只剩下一個元素。

時間復雜度:O(nlogn)

空間復雜讀:O(nlogn)

跟快排是一樣的。

堆排序也是不穩定的排序方法,這一定要搞清楚。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM