/*
* fatal.h
*/
#include
#include
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(-1)
/*
* testbin.cpp
*/
#include
#include "binomial.h"
#define MaxSize (12000)
int main()
{
BinQueue H;
int i, j;
ElementType AnItem;
H = Initialize();
for (i = 0, j = MaxSize / 2; i < MaxSize; ++i, j = (j + 71) % MaxSize)
{
H = Insert(j, H);
}
j = 0;
while (!IsEmpty(H))
{
if (DeleteMin(H) != j++)
{
printf("Error in DeleteMin, %d\n", j);
}
}
if (j != MaxSize)
{
printf("Error in counting!\n");
}
printf("Done...\n");
return 0;
}
/*
* binomial.h
*/
#ifndef _BINQUEUE_H
#define _BINQUEUE_H
#ifndef NULL
#define NULL (0)
#endif
typedef long ElementType;
#define Infinity (30000L)
#define MaxTrees (14) /* Stores 2^14 - 1 items */
#define Capacity (16383)
struct BinNode;
typedef struct BinNode *BinTree;
struct Collection;
typedef struct Collection *BinQueue;
#ifdef __cplusplus
extern "C" {
#endif
BinQueue Initialize();
void Destroy(BinQueue H);
BinQueue MakeEmpty(BinQueue H);
BinQueue Insert(ElementType Item, BinQueue H);
BinQueue Merge(BinQueue H1, BinQueue H2);
int IsEmpty(BinQueue H);
int IsFull(BinQueue H);
ElementType FindMin(BinQueue H);
ElementType DeleteMin(BinQueue H);
#ifdef __cplusplus
}
#endif
#endif /* _BINQUEUE_H */
/*
* binomial.cpp
*/
#include
#include "fatal.h"
#include "binomial.h"
typedef struct BinNode *Position;
struct BinNode
{
ElementType Element;
Position LeftChild;
Position NextSibling;
};
struct Collection
{
int CurrentSize;
BinTree TheTrees[MaxTrees];
};
BinQueue Initialize()
{
BinQueue H;
int i;
H = (BinQueue)malloc(sizeof(struct Collection));
if (H == NULL)
{
FatalError("Out of space!");
}
H->CurrentSize = 0;
for (i = 0; i < MaxTrees; ++i)
{
H->TheTrees[i] = NULL;
}
return H;
}
static void DestroyTree(BinTree T)
{
if (T != NULL)
{
DestroyTree(T->LeftChild);
DestroyTree(T->NextSibling);
free(T);
}
}
void Destroy(BinQueue H)
{
int i;
for (i = 0; i < MaxTrees; ++i)
{
DestroyTree(H->TheTrees[i]);
}
}
BinQueue MakeEmpty(BinQueue H)
{
int i;
Destroy(H);
for (i = 0; i < MaxTrees; ++i)
{
H->TheTrees[i] = NULL;
}
return H;
}
BinQueue Insert(ElementType Item, BinQueue H)
{
BinTree NewNode;
BinQueue OneItem;
NewNode = (BinTree)malloc(sizeof(struct BinNode));
if (NewNode == NULL)
{
FatalError("Out of space!");
}
NewNode->LeftChild = NULL;
NewNode->NextSibling = NULL;
NewNode->Element = Item;
OneItem = Initialize();
OneItem->CurrentSize = 1;
OneItem->TheTrees[0] = NewNode;
return Merge(H, OneItem);
}
BinTree CombineTrees(BinTree T1, BinTree T2)
{
if (T1->Element > T2->Element)
{
return CombineTrees(T2, T1);
}
T2->NextSibling = T1->LeftChild;
T1->LeftChild = T2;
return T1;
}
BinQueue Merge(BinQueue H1, BinQueue H2)
{
BinTree T1, T2, Carry = NULL;
int i, j;
if (H1->CurrentSize + H2->CurrentSize > Capacity)
{
FatalError("Merge would exceed capacity!");
}
H1->CurrentSize += H2->CurrentSize;
for (i = 0, j = 1; j <= H1->CurrentSize; ++i, j *= 2)
{
T1 = H1->TheTrees[i];
T2 = H2->TheTrees[i];
switch (!!T1 + 2 * !!T2 + 4 * !!Carry)
{
case 0: /* No trees */
case 1: /* Only H1 */
break;
case 2: /* Only H2 */
H1->TheTrees[i] = T2;
H2->TheTrees[i] = NULL;
break;
case 4: /* Only Carry */
H1->TheTrees[i] = Carry;
Carry = NULL;
break;
case 3: /* H1 and H2 */
Carry = CombineTrees(T1, T2);
H1->TheTrees[i] = NULL;
H2->TheTrees[i] = NULL;
break;
case 5: /* H1 and Carry */
Carry = CombineTrees(T1, Carry);
H1->TheTrees[i] = NULL;
break;
case 6: /* H2 and Carry */
Carry = CombineTrees(T2, Carry);
H2->TheTrees[i] = NULL;
break;
case 7: /* All threes */
H1->TheTrees[i] = Carry;
Carry = CombineTrees(T1, T2);
H2->TheTrees[i] = NULL;
break;
}
}
return H1;
}
int IsEmpty(BinQueue H)
{
return H->CurrentSize == 0;
}
int IsFull(BinQueue H)
{
return H->CurrentSize == Capacity;
}
ElementType FindMin(BinQueue H)
{
int i;
ElementType MinItem;
if (IsEmpty(H))
{
FatalError("Empty binomial queue!");
}
MinItem = Infinity;
for (i = 0; i < MaxTrees; ++i)
{
if (H->TheTrees[i]
&& H->TheTrees[i]->Element < MinItem)
{
MinItem = H->TheTrees[i]->Element < MinItem;
}
}
return MinItem;
}
ElementType DeleteMin(BinQueue H)
{
int i, j;
int MinTree; /* The tree with the minimum item */
BinQueue DeletedQueue;
Position DeletedTree, OldRoot;
ElementType MinItem;
if (IsEmpty(H))
{
FatalError("Empty binomial queue!");
}
MinItem = Infinity;
for (i = 0; i < MaxTrees; ++i)
{
if (H->TheTrees[i]
&& H->TheTrees[i]->Element < MinItem)
{
/* Update minimum */
MinItem = H->TheTrees[i]->Element;
MinTree = i;
}
}
DeletedTree = H->TheTrees[MinTree];
OldRoot = DeletedTree;
DeletedTree = DeletedTree->LeftChild;
free(OldRoot);
DeletedQueue = Initialize();
DeletedQueue->CurrentSize = (1 << MinTree) - 1;
for (j = MinTree - 1; j >= 0; j--)
{
DeletedQueue->TheTrees[j] = DeletedTree;
DeletedTree = DeletedTree->NextSibling;
DeletedQueue->TheTrees[j]->NextSibling = NULL;
}
H->TheTrees[MinTree] = NULL;
H->CurrentSize -= DeletedQueue->CurrentSize + 1;
Merge(H, DeletedQueue);
return MinItem;
}