排序演算法 堆排序

2021-10-12 04:58:35 字數 2044 閱讀 8695

堆排序是一種時間複雜度在o(n

ln⁡n)

o(n\ln n)

o(nlnn)

的排序方式

它利用了一種叫"堆"的資料結構

此「堆」非彼「堆」,和記憶體裡面的「堆」、「棧」是不一樣的。它是一種基於二叉樹的資料結構

堆的特點是,根結點是子節點的最大值或者最小值

子節點的最值全部都堆在根結點上了,所以這個資料結構叫堆(強行自圓其說)

介紹一下使用陣列模擬二叉樹構造堆的方法

為什麼要使用陣列模擬呢?因為在實際的使用中陣列比鍊錶更加方便,我不希望為了給幾個元素進行排序而寫幾十行**來構建乙個鍊錶,也不希望大部分時間都耗費在申請記憶體和等待之中。

要使用陣列進行二叉樹模擬,首先要對二叉樹的結構有清晰的認識

以下是幾個會用得到的性質:

完全二叉樹:最下面兩層結點的degree可以小於2,最後一層葉節點集中在左邊位置上。顯然我們需要構建完全二叉樹

根結點i的子節點為2i+12i+2

深度為k

kk的二叉樹至多有2∗k

−12*k-1

2∗k−

1個節點

構建乙個根結點是子節點的最大值(僅以最大值為例)

可以使用遞迴方法

void

maxheapify

(int

*arr,

int start,

int end)

使用非遞迴方法速度更快:

void

maxheapify

(int

*arr,

int start,

int end)

}

在構造好堆後,因為每乙個子樹的根結點都是這個子樹裡最大的元素

因此,我們得出了根結點是最大的元素的結論

而第二大的元素和第三大的元素分別存放在根結點的左右子葉中,順序不固定

在構造好了堆這個結構後,我們有了新的想法:

既然堆這個結構中,最大的元素必然在根結點處,那麼,我把根結點和最後乙個節點進行交換,最後乙個節點處就必然是最大的元素了

此時,我再把最後的乙個節點排除在堆外,重建好堆後,然後再次重複上面這個過程,每次都可以將最大的元素放置到最後乙個節點處

當堆裡面沒有元素可以再排除的時候,陣列就可以構建完畢了

void

heapsort

(int

*arr,

int size)

}

對該演算法進行測試。規模為1000~100000,步長為1000

測試結果圖如下

排序演算法 堆排序

1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...

排序演算法 堆排序

花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...

排序演算法 堆排序

由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...