15. 二项队列

fatal.h

#include <stdio.h>
#include <stdlib.h>

#define Error(Str)        FatalError(Str)
#define FatalError(Str)   fprintf(stderr, "%s\n", Str), exit(1)

binomial.h

typedef long ElementType;
#define Infinity (30000L)

#ifndef _BinHeap_H
#define _BinHeap_H

#define MaxTrees (14)   /* Stores 2^14 -1 items */
#define Capacity (16383)

struct BinNode;
typedef struct BinNode *BinTree;
struct Collection;
typedef struct Collection *BinQueue;

BinQueue Initialize(void);
void Destroy(BinQueue H);
BinQueue MakeEmpty(BinQueue H);
BinQueue Insert(ElementType Item, BinQueue H);
ElementType DeleteMin(BinQueue H);
BinQueue Merge(BinQueue H1, BinQueue H2);
ElementType FindMin(BinQueue H);
int IsEmpty(BinQueue H);
int IsFull(BinQueue H);
#endif

binomial.c

#include "binomial.h"
#include "fatal.h"

typedef struct BinNode *Position;

struct BinNode
{
    ElementType Element;
    Position    LeftChild;
    Position    NextSibling;
};

struct Collection
{
    int CurrentSize;
    BinTree TheTrees[MaxTrees];
};

BinQueue Initialize(void)
{
    BinQueue H;
    int i;

    H = 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;
    H->CurrentSize = 0;

    return H;
}

/* Not optimized for O(1) amortized performance */
BinQueue Insert(ElementType Item, BinQueue H)
{
    BinTree NewNode;
    BinQueue OneItem;

    NewNode = malloc(sizeof(struct BinNode));
    if (NewNode == NULL)
        FatalError("Out of space!!!");
    NewNode->LeftChild = NewNode->NextSibling = NULL;
    NewNode->Element = Item;

    OneItem = Initialize();
    OneItem->CurrentSize = 1;
    OneItem->TheTrees[0] = NewNode;

    return Merge(H, OneItem);
}

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))
    {
        Error("Empty binomial queue");
        return -Infinity;
    }

    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;
}

ElementType FindMin(BinQueue H)
{
    int i;
    ElementType MinItem;

    if (IsEmpty(H))
    {
        Error("Empty binomial queue");
        return 0;
    }

    MinItem = Infinity;
    for (i = 0; i < MaxTrees; i++)
    {
        if (H->TheTrees[i] &&
            H->TheTrees[i]->Element < MinItem)
            MinItem = H->TheTrees[i]->Element;
    }

    return MinItem;
}

int IsEmpty(BinQueue H)
{
    return H->CurrentSize == 0;
}

int IsFull(BinQueue H)
{
    return H->CurrentSize == Capacity;
}

/* Return the result of merging equal-sized T1 and T2 */
BinTree CombineTrees(BinTree T1, BinTree T2)
{
    if (T1->Element > T2->Element)
        return CombineTrees(T2, T1);
    T2->NextSibling = T1->LeftChild;
    T1->LeftChild = T2;
    return T1;
}

/* Merge two binomial queues */
/* Not optimized for early termination */
/* H1 contains merged result */
BinQueue Merge(BinQueue H1, BinQueue H2)
{
    BinTree T1, T2, Carry = NULL;
    int i, j;

    if (H1->CurrentSize + H2->CurrentSize > Capacity)
        Error("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] = 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 three */
            H1->TheTrees[i] = Carry;
            Carry = CombineTrees(T1, T2);
            H2->TheTrees[i] = NULL;
            break;
        }
    }
    return H1;
}
posted @ 2017-02-10 03:34  typewriter  阅读(341)  评论(0编辑  收藏  举报