陣列實現“堆”(資料結構)
阿新 • • 發佈:2019-01-22
“堆”是一種特殊的樹形資料結構,他滿足堆的特性:父節點一定不會小於子節點(或大於)。
所有的堆都有著完全二叉樹的結構,與完全二叉樹不同的就是堆的左子節點的值和右子節點的值沒有特定的大小關係。
陣列實現堆相對於連結串列更好理解,但相應的也需要標記出陣列的游標位置和陣列的大小, 需要注意堆實際上是在陣列下標為1處開始的,下標為0處存放一個超過資料界限的最大值。
下面以一個最大堆為例子:
結構體:
typedef struct Heap
{
ElementType *data;
int size;
int MAX_SIZE;
}Heap, *hLink;
建立空堆:
向該堆中插入一個值:hLink CreatHeap(int MAX_SIZE) { hLink k = (hLink)malloc(sizeof(Heap)); k->data = (ElementType*)malloc(sizeof(ElementType)); k->MAX_SIZE = MAX_SIZE; k->size = 0; k->data[0] = 100; return k; }
陣列的插入位置決定了樹上插入的位置,根據規律能得出:“每個節點的父母節點所在的陣列位置” * 2 = 該節點位置。
void Insert(hLink L, ElementType num) { if(L->MAX_SIZE == L->size) { printf("Full!\n"); return; } int i = ++L->size; for(; L->data[i/2] < num; i/=2) { L->data[i] = L->data[i/2]; } L->data[i] = num; }
從最大堆中刪除一個最大值或最小堆中刪除一個最小值(即刪除堆頂元素)
刪除就是:將根節點的值改為最後一個節點的值,size減一,然後一步一步的將在根節點的權值改到適合其所在的位置的過程。
ElementType Delete(hLink L) { int Parent, Child; ElementType maxOne, mid; if(!L->size) { printf("Empty!\n"); return -1; } maxOne = L->data[0]; mid = L->data[size--]; for(Parent = 1; Parent*2 <= L->size; Parent = Child) { Child = Parent * 2; if(Child < L->size&& L->data[Child] < L->data[Child + 1]) { Child++; } if(L->data[Child] < mid) { break; } L->data[Parent] = L->data[Child]; } L->data[Parent] = mid; return maxOne; }
初始化一個堆
初始化一個堆的方法有兩種,一種就是:
每讀取一個元素,就以插入的形式插入一個堆中,但花費時間較多,時間為:O(N*log(N));
另一種方法即為:
先將元素存入data陣列中,然後再將元素進行堆排序,這個方法用時較短,為O(log(N));
堆排序:
堆排序的思想就是:因為陣列存的元素之間不能構成堆,故從最後一個擁有子節點的節點開始執行類似於刪除節點的演算法,然後逐步向前使得每個有子樹的節點都滿足堆的定義,最終形成堆。
void Ordering(hLink H, int pos)
{
int Parent, Child;
ElementType one;
one = H->data[pos];
for(Parent = pos; Parent * 2 <= H->size; Parent = Child)
{
Child = 2 * Parent;
if(Child < H->size&& H->data[Child] < H->data[Child + 1])
{
Child++;
}
if(H->data[Child] < one)
{
break;
}
H->data[Parent] = H->data[Child];
}
H->data[Parent] = one;
}
void InitHeap(hLink H)
{
int N;
scanf("%d", &N);
int i;
ElementType mid;
for(i = 1; i <= N; i++)
{
scanf("%d", &mid);
H->data[i] = mid;
}
H->size = N;
int pos = N / 2;
for(; pos > 0; pos--)
{
Ordering(H, pos);
}
}