堆操作
實驗目的
(一)建堆:將陣列a[1..n]變成乙個最大堆。
(二)堆排序:將乙個堆中的元素按遞減排序輸出。
(三)用插入方法建堆:堆大小從1到n每次插入乙個元素到堆中,直到n個元素入堆。
實驗原理
(二叉)堆是乙個陣列,它可以被看成乙個近似的完全二叉樹。樹上的每乙個結點對應陣列中的乙個元素。除了最底層外,該樹是完全充滿的,而且是從左向右填充。表示堆的陣列a包括兩個屬性:a.length(通常)給出陣列元素的個數,a.heap-size表示有多少個堆元素儲存在該陣列中。也就是說,雖然a[1..a.length]可能都存有資料,但是只有a[1..a.heap-size]中存放的是堆的有效元素,這個,0 <=a.heap-size <= a.length 。樹的根節點是a[1]。
二叉堆可以分為兩種形式:最大堆和最小堆。在這兩種堆中,結點的值都要滿足堆的性質,但一些細節定義則有所差異。在最大堆中,最大堆性質是指除了根以外的所有結點i都要滿足:a[parent(i)] >= a[i] ,也就是說,某個結點的值至多與其父結點一樣大。因此,堆中的最大元素存放在根結點中;並且,在任一子樹中,該子樹所包含的所有結點的值都不大於該子樹根節點的值。最小堆的組織方式正好相反:最小堆性質是指除了根以外的所有結點i都有a[parent(i)] <= a[i] ,最小堆中的最小元素存放在根結點中。
實驗過程
(一)維護堆的性質
max-heapify是用於維護最大堆性質的重要過程。它的輸入為乙個陣列a和乙個下標i。在呼叫max-heapify的時候,對於違背了最大堆的性質的a[i]使其在最大堆中「逐級下降」,從而使得以下標i為根結點的子樹重新遵循最大堆的性質。
max-heapify(a, i)
1 l = left(i)
2 r = right(i)
3 if l <= a.heap-size anda[l] > a[i]
4 largest = l
5 else largest = i
6 if r <= a.heap-size anda[r] > a[largest]
7 largest = r
8 if largest != i
9 exchange a[i] with a[largest]
10 max-heapify(a, largest)
(二)建堆
我們可以用自底向上的方法利用過程max-heapify把乙個大小為n = a.length的陣列a[1..n]轉換為最大堆。子陣列a(|n/2|+1..n)中的元素都是樹的葉節點。對每乙個葉節點都呼叫max-heapify進行調整,從而滿足最大堆的性質。
(三)堆排序
由於陣列中的最大元素總是在根結點a[1]中,通過把它與a[n]進行互換,我們可以讓該元素放到正確的位置。這個時候,我們從堆中去掉結點n(即通過減少a.heap-size的值來實現),剩餘的節點中,原來根的孩子仍然是最大堆,而新的節點可能違背最大堆的性質,為了維護最大堆的性質,呼叫一次max-heapify(a, 1),從而在a[1..n-1]上構造乙個新的最大堆。
(四)插入方法建堆
max-heap-insert能夠實現insert操作。它的輸入是要被插入到最大堆a中的新元素的關鍵字。max-heap-insert首先通過增加乙個關鍵字為-∞的葉節點來擴充套件最大堆,然後呼叫heap-increase-key為新節點設定對應的關鍵字,同時保持最大堆的性質。
實驗總結
(一)將整個實驗過程完成後,深入理解了二叉堆的性質。堆的優點:在大多數計算機上,在實現parent(i),left(i),right(i)過程中,可以通過較少的指令(左移,右移)進行計算。
(二)在建堆的過程中,有乙個巧妙的地方:就是對於a[|a.length/2|..1]的葉節點進行最大堆的性質維護,而不是遍歷整個堆。
(三)堆排序的實際應用場景:基於最大堆實現最大優先佇列(記錄將要執行的各個作業以及它們之間的相對優先順序),從而應用到計算機系統的作業排程中。
附錄(**)
(一)建堆
#include
#include
#define a_length 10
int a_heap_size;
void max_heapify(int a, int i)
}void build_max_heap(int a)
int main();
int i;
printf("origin_heapa=");
for(i = 0; i< 10; i++)
printf("%d ",a[i]);
printf("\n");
build_max_heap(a);
printf(" max_heap a=");
for(i = 0; i< 10; i++)
printf("%d ",a[i]);
printf("\n");
}
(二)堆排序
#include
#include
#define a_length 10
int a_heap_size;
void max_heapify(int a, int i)
}void build_max_heap(int a)
void heapsort(int a)
}int main();
int i;
printf("origin_heapa=");
for(i = 0; i< 10; i++)
printf("%d ",a[i]);
printf("\n");
build_max_heap(a);
printf(" max_heap a=");
for(i = 0; i< 10; i++)
printf("%d ",a[i]);
printf("\n");
heapsort(a);
printf("heap_sort a=");
for(i = 0; i< 10; i++)
printf("%d ",a[i]);
printf("\n");
}
(三)用插入法建堆
#include
#include
#define a_length 10
int a_heap_size;
int insert_length;
int parent(int i)
void heap_increase_key(int a, int i, int key)
}void max_heap_insert(int a, int key)
void build_max_heap(int a)
}int main()
初步了解二叉堆(二叉堆及其基本操作)
如圖,簡單來說,二叉堆是一棵滿足 堆性質 的完全二叉樹,樹上的每乙個節點都帶有乙個權值。若樹中任意的乙個節點的權值都小於等於其父節點的權值,則稱滿足該性質的完全二叉樹為大根堆 根權值最大 若樹中任意的乙個節點的權值都大於等於其父節點的權值,則稱滿足該性質的完全二叉樹為小根堆 根權值最小 二叉樹是一種...
簡單 二叉堆
堆是一種比較有用的資料結構,是二叉樹的一種陣列的表示形式。最大堆和最小堆是二叉堆的兩種形式。最大堆 根結點的鍵值是所有堆結點鍵值中最大者。最小堆 根結點的鍵值是所有堆結點鍵值中最小者。而最大 最小堆集結了最大堆和最小堆的優點,這也是其名字的由來。最大 最小堆是最大層和最小層交替出現的二叉樹,即最大層...
演算法 二叉堆
二叉堆具體來說就是支援插入刪除查詢最值的資料結構,是一棵滿足堆性質的完全二叉樹,樹上的每乙個節點對應乙個權值。若樹中的任意乙個節點的權值都小於其父節點的權值,則稱該二叉樹滿足大根堆性質,即我們常說的大根堆。若書中任意乙個節點的全職都打與其父親節點的權值,則稱該二叉樹滿足小根堆性質,即小根堆。二者統稱...