一. 堆排序
1. 堆:類似於完全二叉樹,有a1,a2,a3, ... an,個元素,且第 2*i+1 和 2*i+2 位置的關鍵字都小於或大於第 i 位置的關鍵字。
2. 大根堆與小根堆
大根堆:堆中的所有元素都滿足第 2*i+1 和 2*i+2 位置的關鍵字都小於第 i 位置的關鍵字。
小根堆:堆中的所有元素都滿足第 2*i+1 和 2*i+2 位置的關鍵字都大於第 i 位置的關鍵字。
3. 堆排序:利用堆積樹(堆)這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。在陣列的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。
二. 原理
1. 用大根堆排序的基本思想
① 先將初始檔案r[1..n]建成乙個大根堆,此堆為初始的無序區
② 再將關鍵字最大的記錄r[1](即堆頂)和無序區的最後乙個記錄r[n]交換,由此得到新的無序區r[1..n-1]和有序區r[n],且滿足r[1..n-1].keys≤r[n].key
③由於交換後新的根r[1]可能違反堆性質,故應將當前無序區r[1..n-1]調整為堆。然後再次將r[1..n-1]中關鍵字最大的記錄r[1]和該區間的最後乙個記錄r[n-1]交換,由此得到新的無序區r[1..n-2]和有序區r[n-1..n],且仍滿足關係r[1..n-2].keys≤r[n-1..n].keys,同樣要將r[1..n-2]調整為堆。
……直到無序區只有乙個元素為止。
2. 例如:對資料進行排列如下圖:
三. **實現 -- 大根堆排序
#include
using namespace std;
//一次堆調整 -- 大根堆
static heap(int* arr, int start, int end)
if(tmp < arr[i])
else
}arr[parent] = tmp;
}//堆排序 -- 大根堆
void heapsort(int* arr, int len)
//建立大根堆
for(int i=(len-1-1)/2; i>=0; i--)
//一次堆調整
for(int i=0; i
四. 時間複雜度和空間複雜度及穩定性
1. 時間複雜度
首先建立大根堆時,需要從(len-1-1)/2處不斷調整,整個是線性的過程時間複雜度為o(n),然後對len-1個資料進行一次堆調整,直至無序區只剩下乙個資料,這個過程的時間複雜度為o((n-1)*lgn),所以整個排序過程總的算下來為o(n*lgn)。
2. 空間複雜度
縱觀整個排序過程除了區域性臨時變數外,未借用其它額外的空間,所以空間複雜度為o(1)。
3. 穩定性
無論是**還是例圖我們都可以看出,堆排序過程中是2*i+1 或 2*i+2 位置的關鍵字與 i 處的進行交換,這種跳躍式的資料交換使得此排序不穩定。
排序演算法 堆排序
1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...
排序演算法 堆排序
花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...
排序演算法 堆排序
由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...