【筆記】堆及其實現
有一種特殊形式的完全二叉樹——堆,它有兩種基本形式:最大堆和最小堆。
最大堆:如果一顆完全二叉樹的任意一個非終結結點的元素都不小於其左兒子結點和右兒子結點的元素,則稱此完全二叉樹為最大堆。
最小堆:如果一顆完全二叉樹的任意一個非終結結點的元素都不大於其左兒子結點和右兒子結點的元素,則稱此完全二叉樹為最小堆。
最大堆的根結點中的元素在整個堆中是最大的;而最小堆的根結點中的元素在整個堆中是最小的。
當把最大堆看做抽象資料型時,有以下幾個基本操作:
- MaxHeap(heap):建立一個空堆,最多可以容納MaxSize個元素。
- Insert(heap,item):判斷堆是否為滿。
- HeapEmpty(heap):插入一個元素。
- DeleteMax(heap):刪除最大元素。
由於最大堆是一顆完全二叉樹,所以最大堆可以用一維陣列來表示。
- 最大堆的型別定義
#define Maxsize 200
typedef struct
{
int key;
/*other fields*/
}Elementtype;
typedef struct
{
Elementtype elements[Maxsize];
int n;
}HEAP;
- 建立一個空堆
初始時,堆的元素個數計數器n為零,
void MaxHeap(HEAP *heap)
{
heap->n=0;
}
- 判斷堆是否為空
int HeapEmpty(HEAP heap)
{
return(!heap.n);
}
- 堆中插入一個元素
當要插入一個元素時,為了保持完全二叉樹的結構性質,新增結點的編號應為i=n+1。同時,為了保持最大堆的性質,還要把結點i的元素與其父結點的元素進行比較。如果結點i的元素大於其父結點的元素,則將結點i的元素與其父結點的元素進行交換,並令結點i的父結點成為新結點i,繼續向上比較,直到結點i的元素不大於其父結點的元素或者i到達根結點為止。
由於堆是一顆完全二叉樹,因此具有n個元素的堆,其高度為[log(n+1)]。這就意味著while迴圈要重複O(logn)次,因此插入函式的時間複雜性為O(logn)。
void Insert(HEAP *heap,Elementtype element)
{
int i;
i=heap->n+1;
while( (i!=1)&&(element.key>heap->elements[i/2].key))
{
heap->elements[i]=heap->elements[i/2];
i/=2;
}
heap->elements[i]=element;
heap->n++;
}
- 堆中刪除一個元素
在最大堆中刪除最大元素時,一定是從堆的根結點中刪除元素。為了在刪除結點後保持完全二叉樹的結構性質,把最後一個結點(編號最大的葉結點n)的元素暫存在根節點i=1中,此時完全二叉樹中元素的個數變為n-1,但可能不符合最大堆的定義。為了保持最大堆的性質,還需要比較結點i的元素預期較大兒子結點的元素。如果結點i的元素小於其較大兒子結點的元素,則將結點i與其較大兒子結點的元素對換,並令結點i的較大兒子結點成為新的結點i,繼續向下比較,直到結點i的元素不小於其較大兒子結點的元素或者i到達葉結點為止。
刪除操作的時間複雜性為O(logn)。
Elementtype DeleteMax(HEAP *heap)
{
int parent=1,child=2;
Elementtype element,tmp;
if(!HeapEmpty(*heap))
{
element=heap->elements[1];
tmp=heap->elements[heap->n--];
while(child <= heap->n)
{
if((child<heap->n)&&(heap->elements[child].key<heap->elements[child+1].key))
child++;
if(tmp.key >= heap->elements[child].key)
break;
heap->elements[parent]=heap->elements[child];
parent=child;
child*=2;
}
heap->elements[parent]=tmp;
return element;
}
}
- 主函式
int main()
{
int n,i;
HEAP h;
MaxHeap(&h);
printf("請輸入要插入的元素個數:(不超過200)");
scanf("%d",&n);
while(n>Maxsize)
{
printf("元素個數超出堆的容量!請重新輸入:");
scanf("%d",&n);
}
Elementtype a[n+1],x;
printf("請依次輸入每個元素的值:");
for (i = 1; i <= n; i++)
{
scanf("%d",&a[i].key);
Insert(&h, a[i]);
}
while (!HeapEmpty(h))
{
x = DeleteMax(&h);
printf("%d", x.key);
if (!HeapEmpty(h))
printf(",");
}
printf("\n");
return 0;
}
- 測試結果
經常使用堆來實現優先順序佇列。優先順序佇列只對最高(或最低)優先順序的元素進行刪除。但是在任何時候,都可以把任意優先順序的元素插入到優先順序佇列。如果應用程式要求刪除最高優先順序的元素,就使用最大堆。如果應用程式要求刪除最低優先順序的元素,則使用最小堆。
相關文章
- 學習筆記----快速排序的java實現及其改良筆記排序Java
- Linux堆管理實現原理學習筆記 (上半部)Linux筆記
- 設計模式學習筆記(二十)狀態模式及其實現設計模式筆記
- 設計模式學習筆記(十八)備忘錄模式及其實現設計模式筆記
- 堆外記憶體及其在 RxCache 中的使用記憶體
- 堆的實現
- 堆溢位學習筆記筆記
- 【JVM】堆體系結構及其記憶體調優JVM記憶體
- 設計模式學習筆記(二十一)訪問者模式及其實現設計模式筆記
- 設計模式學習筆記(二十二)直譯器模式及其實現設計模式筆記
- 吳恩達《Machine Learning》精煉筆記 9:PCA 及其 Python 實現吳恩達Mac筆記PCAPython
- 堆和索引堆的python實現索引Python
- PHP 實現堆, 堆排序以及索引堆PHP排序索引
- 筆記本省電問題分析及其實用小技巧筆記
- 堆的原理與實現
- 【讀書筆記+小練習(答案已經更新)】作業系統——程式及其實現筆記作業系統
- ACM學習筆記:二叉堆ACM筆記
- *衡樹 Treap(樹堆) 學習筆記筆記
- 堆溢位-House of orange 學習筆記筆記
- 圖的深度優先遍歷(堆疊實現和非堆疊實現)
- 【筆記】oracle 陣列實現筆記Oracle陣列
- 深度學習筆記:CNN經典論文研讀之AlexNet及其Tensorflow實現深度學習筆記CNN
- 吳恩達《Machine Learning》精煉筆記 8:聚類 KMeans 及其 Python實現吳恩達Mac筆記聚類Python
- 【資料結構】——堆及其應用資料結構
- ThreadDump分析筆記(一) 解讀堆疊thread筆記
- 左傾堆以及Java實現Java
- 字首樹及其Java實現Java
- AOP如何實現及其原理
- Set介面及其實現類
- 線性表及其實現
- 分散式鎖及其實現分散式
- KgCaptcha驗證碼實現筆記GCAPT筆記
- 【筆記】樹的表示與實現筆記
- Java實現Kafka讀寫筆記JavaKafka筆記
- Chakra TypedArray程式碼實現筆記筆記
- 《自我實現的人》讀書筆記筆記
- 大頂堆的python實現Python
- 堆的原理以及實現O(lgn)