堆是一種靈巧的、部分有序的資料結構,它尤其適合用來實現優先佇列。
優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱為元素優先順序的可排序屬性。優先佇列支援下面的操作:
通過採用堆這種資料結構可以高效實現這些操作。
下文分兩部分:第一部分介紹堆;第二部分講解堆排序。
堆可以定義為一棵二叉樹,樹的節點中包含鍵(每個節點乙個鍵),並且滿足下面兩個條件:
樹的形狀要求--這棵二叉樹是基本完備的(或者簡稱完全二叉樹),這意味著,樹的每一層都是滿的,除了最後一層最右邊的元素有可能缺位。
父母優勢要求--每乙個節點的鍵都要大於或等於它子女的鍵(對於任何葉子我們認為這個條件都是自動滿足的)。(最大堆)
在堆中,鍵值是從上到下排序的。在任何從根到某個葉子的路徑上,鍵值的序列式遞減的。鍵值之間不存在從左到右的次序。在樹的同一層的節點之間,不存在任何關係。在同一節點的左右子樹之間也沒有任何關係。
堆的重要特徵:
只存在一棵n個節點的完全二叉樹。它的高度等於log2n。
堆的根總是包含了堆的最大元素。
堆的乙個節點以及該節點的子孫也是乙個堆。
可以用陣列來實現堆,方法是用從上到下、從左到右的方式來記錄堆的元素。為了方便起見,可以在這種陣列從1到n的位置上存放堆元素,留下h[0](可以在其中放乙個限位器)。在這種表示法中:
a. 父母節點的鍵將會位於陣列的前[n / 2]個位置中,而葉子節點的鍵將會佔據後[n / 2]個位置。
b. 在陣列中,對於乙個位於父母位置i(1<=i<=[n / 2])的鍵來說,它的子女將會位於2i和2i+1,相應地,對於乙個位於i(2<=i<=n)的鍵來說,它的父母將會位於[i/2]。
我們可以將堆定義為乙個陣列h[1…n],其中,陣列前半部分中每個位置i上的元素,總是大於等於位置2i和2i+1中的元素。
對於i=1,…,[n / 2], h[i]>=max
從最後的父母節點開始,到根為止,檢查這些節點的鍵是否滿足父母優勢要求。如果該節點不滿足,則把節點的鍵k和它子女的最大鍵進行交換,然後再檢查在新位置上,k是不是滿足父母優勢要求。這個過程一直持續到,對k的父母優勢要求滿足為止。對於以當前父母節點為根的子樹,在完成了它「堆化」以後,該演算法對於該幾點的直接前趨進行同樣的操作,直到對樹的根完成了這種操作以後,該演算法就停止。
演算法 heapbottomup(h[1..n])
//用自底向上演算法,從給定陣列的元素中構建乙個堆
//輸入:乙個可排序元素的陣列h[1..n]
//輸出:乙個堆h[1..n]
從堆中刪除最大的鍵
第一步:根的鍵和堆的最後乙個鍵k做交換。
第二步:堆的規模減一。
第三步:嚴格按照自底向上堆構造演算法把k沿著樹向下刪選,來對這棵較小的樹進行「堆化」。驗證k是否滿足父母優勢:如果它滿足,操作完成;如果不滿足,k和它較大的子女做交換;然後重複這個操作,直到k在新位置中滿足了父母優勢要求為止。
堆排序是由j.w.j.williams提出。堆排序的時間效率輸入o(nlogn)。這個演算法分為兩步:
第一步:(構造堆)為乙個給定的陣列構造乙個堆。
第二部:(刪除最大鍵)對剩下的堆應用n-1次根刪除操作。
對於堆的陣列實現來說,乙個正在被刪除元素師位於最後的,所以結果陣列將敲好是按照公升序排列的原始陣列。
#include #include //陣列從1到n的位置上存放堆元素,a[0]不參與構造堆。
//可以將a[0]空著,也可以在其中放乙個限位器。
/**********自底向上構造最大堆**************/
void heapbottomup(int a, int n)
} a[k] = tmp; }}
/**********自底向上調整最大堆**************/
void fixheapbottomup(int a, int n)
} a[i] = tmp;
}/**********自頂向下調整最大堆**************/
void fixheapupbottom(int a, int n)
} a[i] = tmp;
}/**********插入乙個數**************/
void insertnumber(int a, int n, int num)
/**********刪除最大鍵**************/
int deletenumber(int a, int n)
/**********堆排序**************/
void heapsort(int a, int n)
int main(int argc, const char *argv)
; int n = sizeof(a) / sizeof(int);
heapsort(a, n - 1);
for(int i = 1; i < 7; i ++)
printf("%d ", a[i]);
return 0;
}
堆和堆排序
這個題大意是有乙個資料結構支援兩種操作a與 get操作,其中 a x表示插入 x.get i 表示返回結構中的第 i小的數.給你 a和get操作的順序和引數 現在要你對每個 get輸出值 題解 每次取第k小元素,k不斷更新。使用兩個堆,來完成。小頂堆負責選出最小的元素,大頂堆負責選出k個元素中最大的...
堆和堆排序
堆排序演算法 優先佇列 堆的性質的維護,以下都以最大堆為例。堆的維護的主要思想是 逐層下降 舉例 某個結點i,假設其左右子結點left i right i 都已經是最大堆,那麼需要調節 或者說是調換 i,left i right i 的值,並保證調換後的子樹繼續調換下去直到子樹繼續滿足堆的性質。首先...
堆和堆排序
用陣列來儲存堆,下標為i的結點,父節點的編號為 i 1 2,子結點的編號為2 i 1,2 i 2。建立堆 每次插入乙個元素並調整堆的過程。插入乙個元素 插入到陣列最後,更新樹。刪除乙個元素 刪除發生在nums 0 將最後乙個元素調整到nums 0 處,更新樹。長度為len的陣列,最後乙個葉子節點的父...