二项队列

是对左式树的改进,对于insert操作有O(1)平均时间

源码如下:

#ifdef _cplusplus
extern "C" {
#endif

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

#define MaxTrees 16
#define Infinity 0x80000000

typedef int ElementType;

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

/* 二项队列单个节点,包含指向第一个儿子和兄弟的指针 */
struct BinNode
{
    ElementType Element;
    Position LeftChild;
    Position NextSibling;
};

/* 二项队列管理容器 */
struct Collection
{
    int CurrentSize;
    BinTree TheTrees[MaxTrees];
};

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

BinQueue Initialize()
{
    BinQueue H = NULL;
    H = malloc(sizeof(struct Collection));
    memset(H, 0, sizeof(struct Collection));

    return H;
}

/* 合并两棵树,对于二项队列,T1和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;
}

/* 合并两个二项队列,不能合并自己,否则还要处理 */
BinQueue Merge(BinQueue H1, BinQueue H2)
{
    BinTree T1, T2, Carry = NULL;
    int i, j;

    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)
        {
            /* 什么都没有或者只有T1,不用处理 */
            case 0:
            case 1:
                break;
            /* 只有T2,将T2移动到T1,清零T2 */
            case 2:
                H1->TheTrees[i] = T2;
                H2->TheTrees[i] = NULL;
                break;
            case 4:
                H1->TheTrees[i] = Carry;
                Carry = NULL;
                break;
            /* 若同时有T1和T2,进位到Carry */
            case 3:
                Carry = CombineTrees(T1, T2);
                H1->TheTrees[i] = NULL;
                H2->TheTrees[i] = NULL;
                break;
            case 5:
                Carry = CombineTrees(T1, Carry);
                H1->TheTrees[i] = NULL;
                break;
            case 6:
                Carry = CombineTrees(T2, Carry);
                H2->TheTrees[i] = NULL;
                break;
            /* 3个都有,保留Carry,再次将T1和T2进位 */
            case 7:
                H1->TheTrees[i] = Carry;
                Carry = CombineTrees(T1, T2);
                break;
        }
    }
}

/* 删除最小值并返回 */
ElementType DeleteMin(BinQueue H)
{
    int i, j;
    int MinTree;
    BinQueue DeletedQueue;
    Position DeletedTree, OldRoot;
    ElementType MinItem;

    /* 遍历所有格子找最小的根 */
    MinItem = Infinity;
    for (i = 0; i < MaxTrees; i++)
    {
        if (H->TheTrees[i] && H->TheTrees[i]->Element < MinItem)
        {
            MinItem = H->TheTrees[i]->Element;
            MinTree = i;
        }
    }

    /* 保存最小根的第一个左儿子并删除这个根 */
    DeletedTree = H->TheTrees[MinTree];
    OldRoot = DeletedTree;
    DeletedTree = DeletedTree->LeftChild;
    free(OldRoot);

    /* 收集删除根后剩下的树,放到DeletedQueue中 */
    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;
}

void main()
{

}

#ifdef _cplusplus
}
#endif

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值