1. 概述
堆(也叫優先佇列),是一棵完全二叉樹,它的特點是父節點的值大於(小於)兩個子節點的值(分別稱為大頂堆和小頂堆)。它常用於管理演算法執行過程中的資訊,應用場景包括堆排序,優先佇列等。
2. 堆的基本操作
堆是一棵完全二叉樹,高度為o(lg n),其基本操作至多與樹的高度成正比。在介紹堆的基本操作之前,先介紹幾個基本術語:
a:用於表示堆的陣列,下標從1開始,一直到n
parent(t):節點t的父節點,即floor(t/2)
right(t):節點t的左孩子節點,即:2*t
left(t):節點t的右孩子節點,即:2*t+1
heap_size(a):堆a當前的元素數目
下面給出其主要的四個操作(以大頂堆為例):
2.1 heapify(a,n,t)
該操作主要用於維持堆的基本性質。假定以right(t)和left(t)為根的子樹都已經是堆,然後調整以t為根的子樹,使之成為堆。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void
heapify(
int
a,
int
n,
int
t)
}
2.2 buildheap(a,n)
該操作主要是將陣列a轉化成乙個大頂堆。思想是,先找到堆的最後乙個非葉子節點(即為第n/2個節點),然後從該節點開始,從後往前逐個調整每個子樹,使之稱為堆,最終整個陣列便是乙個堆。
1
2
3
4
5
6
7
8
9
10
11
void
buildheap(
int
a,
int
n)
2.3 getmaximum(a,n)
該操作主要是獲取堆中最大的元素,同時保持堆的基本性質。堆的最大元素即為第乙個元素,將其儲存下來,同時將最後乙個元素放到a[1]位置,之後從上往下調整a,使之成為乙個堆。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void
getmaximum(
int
a,
int
n)
2.4 insert(a, n, t)
向堆中新增乙個元素t,同時保持堆的性質。演算法思想是,將t放到a的最後,然後從該元素開始,自下向上調整,直至a成為乙個大頂堆。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void
insert(
int
a,
int
n,
int
t)
a[p] = t;
return
max;
}
3. 堆的應用
3.1 堆排序
堆的最常見應用是堆排序,時間複雜度為o(n lg n)。如果是從小到大排序,用大頂堆;從大到小排序,用小頂堆。
3.2 在o(n lg k)時間內,將k個排序表合併成乙個排序表,n為所有有序表中元素個數。
【解析】取前100 萬個整數,構造成了一棵陣列方式儲存的具有小頂堆,然後接著依次取下乙個整數,如果它大於最小元素亦即堆頂元素,則將其賦予堆頂元素,然後用heapify調整整個堆,如此下去,則最後留在堆中的100萬個整數即為所求 100萬個數字。該方法可大大節約記憶體。
3.3 乙個檔案中包含了1億個隨機整數,如何快速的找到最大(小)的100萬個數字?(時間複雜度:o(n lg k))
4. 總結
堆是一種非常基礎但很實用的資料結構,很多複雜演算法或者資料結構的基礎就是堆,因而,了解和掌握堆這種資料結構顯得尤為重要。
5. 參考資料
(1)經典演算法教程《演算法導論》
———————————————————————————————
更多關於資料結構和演算法的介紹,請檢視:資料結構與演算法彙總
———————————————————————————————-
Heap 資料結構之堆
堆是一種資料結構,是一棵二叉樹 盡量地滿足完全二叉樹的規律 他有乙個特點,就是兩個兒子的值均大於或小於父節點。那麼這個堆就被稱為大頂堆或小頂堆。同一級的元素不比較大小,它可以用到優先佇列之中,還有其他很神奇的應用。其實就是乙個步驟 如果它不滿足堆的性質,那麼就繼續維護,否則結束。1.向上維護 如果節...
資料結構之 堆(Heap)
堆 heap 是電腦科學中一類特殊的資料結構的統稱。堆通常是乙個可以被看做一棵完全二叉樹的陣列物件。同時堆是一種特殊的 佇列 既然說堆是完全二叉樹,那麼就得介紹下什麼是完全二叉樹 定義 若設二叉樹的高度為h,除第h層外,其它各層 1 h 1 的結點數都達到最大個數,且第h層所有的節點都連續集中在最左...
資料結構 堆(heap)
堆 heap 也被稱為優先佇列 priority queue 佇列中允許的操作是先進先出 fifo 在隊尾插入元素,在隊頭取出元素。而堆也是一樣,在堆底插入元素,在堆頂取出元素,但是堆中元素的排列不是按照到來的先後順序,而是按照一定的優先順序排列的。這個優先順序可以是元素的大小或者其他規則。如圖一所...