用一組數建立小堆(堆的建立)
(二叉)堆的概念:
如果有一組數,數的集合K={K0,K1,.....Kn-1},把它的所有元素按照完全二叉樹的順序儲存方式儲存在一個一維陣列中,並且有Ki<=2*Ki+1,Ki<=2*Ki+2,(或者Ki>=2*Ki+1,Ki>=2*Ki+2),稱為小(大)堆。
如上圖所示:
小(大)堆中,任一關鍵碼均小於(大於)等於它的左右孩子的關鍵碼,位於堆頂頂點的關鍵碼最小(最大),從根節點到每個節點的路徑上陣列組成的序列都是遞減(遞增)的。
堆儲存在下標為0開始的陣列中,因此在堆中給定下標為i的節點時:
1)如果i=0,節點是根節點,沒有雙親節點,否則,雙親節點為(i-1)/2
2)如果2*i+1<=n-1,則節點i的左孩子為節點2*i+1,否則節點i無左孩子
3)如果2*i+2<=n-1,則節點i的右孩子為節點2*i+2,否則節點i無右孩子
堆的建立:
(1)將一組數先放進堆定義的結構體中;
(2)向下調整堆
從最後一個非葉子節點開始調整,一直到根節點為止,將每一個節點及其子樹調整到滿足小堆的性質即可。
具體調整方法:
while(1)
{1)若此節點為K;
2)則此節點的左孩子為2*K+1,判斷左孩子是否存在,不存在,結束;存在,向下走。
3)判斷此節點的右孩子2*K+2是否存在,不存在,判斷左孩子與節點K的大小;存在,向下走。
4)比較左右孩子與節點K的大小,若節點K最小,結束;若左孩子最小,左孩子與節點交換,若右孩子最小,右孩子與節點交換。
}
程式碼如下:
標頭檔案:二叉堆.h
#pragma once #include<stdio.h> #include<stdlib.h>
#define Max 100
typedef int DataType; //typedef int size_t;
//二叉堆 typedef struct StackN { DataType array[Max]; //size_t size; int size; }StackN;
void init(StackN * php) { php->size = 0; php = NULL; }
//讓資料入堆 void CreatS(DataType a[], StackN*php, int n) { if (n == 0) { return; printf("內容為空!\n"); } int i = 0; for (i = 0; i < n; i++) { php->array[i] = a[i]; php->size++; } }
void swap(int*a, int *b) { int t = 0; t = *a; *a = *b; *b = t; }
void AdJust(StackN*php, int root) { while (1) { int left = 2 * root + 1; int right = 2 * root + 2; // 判斷是否是葉子結點,如果左孩子下標越界了,沒有左孩子了 // 所以也就沒有右孩子了 if (left >= php->size) { // == 的情況也是越界 // 越界 return; }
int min = left; // 假設大的那個是左孩子 // 找到左右孩子中大的一個 // 一定要先判斷右孩子有,才能比較左右孩子的大小 // if (array[right] > array[left] && right < size),錯誤的 if (right < php->size && php->array[right] < php->array[left]) { min = right; }
// 判斷和 [root] 的關係 // root >= max 錯誤的, root 和 max 表示的下標 if (php->array[root] <= php->array[min]) { return; }
// 交換 int t = php->array[root]; php->array[root] = php->array[min]; php->array[min] = t;
root = min; } }
void A_S(DataType a[], StackN*php) { int i = 0; for (i = (php->size-1)/2; i >= 0; i--) AdJust(php, i); printf("\n"); }
void test() { StackN php; init(&php); DataType aa[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 }; //堆 調整為小堆 int n = sizeof(aa) / sizeof(DataType); CreatS(aa, &php, n);
A_S(aa, &php);
}
原始檔:test.c
#include"二叉堆.h" #include<Windows.h>
int main() { test(); system("pause"); return 0; }