12. 二叉堆(binary heap)
fatal.h
#include <stdio.h>
#include <stdlib.h>
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
binheap.h
typedef int ElementType;
#ifndef _BinHeap_H
#define _BinHeap_H
struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;
PriorityQueue Initialize(int MaxElements);
void Destroy(PriorityQueue H);
void MakeEmpty(PriorityQueue H);
void Insert(ElementType X, PriorityQueue H);
ElementType DeleteMin(PriorityQueue H);
ElementType FindMin(PriorityQueue H);
int IsEmpty(PriorityQueue H);
int IsFull(PriorityQueue H);
void Print(PriorityQueue H);
#endif
binheap.c
#include "binheap.h"
#include "fatal.h"
#include <stdlib.h>
#define MinPQSize (10)
#define MinData (-32767)
struct HeapStruct
{
int Capacity;
int Size;
ElementType *Elements;
};
PriorityQueue Initialize(int MaxElements)
{
PriorityQueue H;
if (MaxElements < MinPQSize)
Error("Priority queue size is too small");
H = malloc(sizeof(struct HeapStruct));
if (H == NULL)
FatalError("Out of space!!!");
/* Allocate the array plus one extra for sentinel */
H->Elements = malloc((MaxElements + 1) * sizeof(ElementType));
if (H->Elements == NULL)
FatalError("Out of space!!!");
H->Capacity = MaxElements;
H->Size = 0;
H->Elements[0] = MinData;
return H;
}
void MakeEmpty(PriorityQueue H)
{
H->Size = 0;
}
/* H->Element[ 0 ] is a sentinel */
void Insert(ElementType X, PriorityQueue H)
{
int i;
if (IsFull(H))
{
Error("Priority queue is full");
return;
}
for (i = ++H->Size; H->Elements[i / 2] > X; i /= 2)
H->Elements[i] = H->Elements[i / 2];
H->Elements[i] = X;
}
ElementType DeleteMin(PriorityQueue H)
{
int i, Child;
ElementType MinElement, LastElement;
if (IsEmpty(H))
{
Error("Priority queue is empty");
return H->Elements[0];
}
MinElement = H->Elements[1];
LastElement = H->Elements[H->Size--];
for (i = 1; i * 2 <= H->Size; i = Child)
{
/* Find smaller child */
Child = i * 2;
if (Child != H->Size && H->Elements[Child + 1] < H->Elements[Child])
Child++;
/* Percolate one level */
if (LastElement > H->Elements[Child])
H->Elements[i] = H->Elements[Child];
else
break;
}
H->Elements[i] = LastElement;
return MinElement;
}
ElementType FindMin(PriorityQueue H)
{
if (!IsEmpty(H))
return H->Elements[1];
Error("Priority Queue is Empty");
return H->Elements[0];
}
int IsEmpty(PriorityQueue H)
{
return H->Size == 0;
}
int IsFull(PriorityQueue H)
{
return H->Size == H->Capacity;
}
void Destroy(PriorityQueue H)
{
free(H->Elements);
free(H);
}
void Print(PriorityQueue H)
{
int i, j;
for (i = 1, j = 1; i <= H->Size; i++)
{
if (i == j)
{
j *= 2;
printf("\n");
}
printf("%d ", H->Elements[i]);
}
printf("\n\n");
}
testheap.c
#include "binheap.h"
#include <stdio.h>
#define MaxSize (33)
int main()
{
PriorityQueue H;
int i, j;
H = Initialize(MaxSize);
for (i = 0, j = MaxSize / 2; i < MaxSize; i++, j = (j + 71) % MaxSize)
{
Insert(j, H);
printf("Insert %d:", j);
Print(H);
}
j = 0;
while (!IsEmpty(H))
{
if (DeleteMin(H) != j++)
printf("Error in DeleteMin, %d", j);
printf("DeleteMin %d:", j - 1);
Print(H);
}
printf("Done...\n");
return 0;
}