教材中二项队列的例程:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MaxTrees 10
#define Capacity 10
typedef struct BinNode *BinTree;
typedef struct BinNode *Position;
typedef struct Collection *BinQueue;
typedef int ElementType;
struct BinNode
{
ElementType Element;
Position LeftChild;
Position NextSibling;
};
struct Collection
{
int CurrentSize;
BinTree TheTrees[MaxTrees];
};
/*Return the result of merging equal-size T1 and T2*/
BinTree CombineTrees(BinTree T1, BinTree T2)
{
BinTree tmp; //如果T1与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)
{
printf("Merge would exceed capacity!!!\n");
exit(0);
}
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 tree*/
H1->TheTrees[i] = Carry;
Carry = CombineTrees(T1, T2);
H2->TheTrees[i] = NULL;
break;
}
}
return H1;
}
ElementType DeleteMin(BinQueue H)
{
int i, j;
int MinTree; /*The tree with the minimun item*/
BinQueue DeleteQueue;
Position DeletedTree, OldRoot;
ElementType MinItem;
if(IsEmpty(H))
{
printf("Empty binomial queue!!!\n");
return INT_MIN;
}
MinItem = INT_MAX;
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);
DeletedTree = Initialize();
DeleteQueue->CurrentSize = (1 << MinTree) - 1;
for(j = MinTree; i >= 0; j--)
{
DeleteQueue->TheTrees[j] = DeletedTree;
DeletedTree = DeletedTree->NextSibling;
DeleteQueue->TheTrees[j]->Element = NULL;
}
H->TheTrees[MinTree] = NULL;
H->CurrentSize -= DeleteQueue->CurrentSize + 1;
Merge(H, DeleteQueue);
return MinItem;
}
a.如果是相同二项队列的合并,那么根节点为出现自反,那么需要创建一个与根节点相同的节点,然后合并到树,修改的代码为:
/*Return the result of merging equal-size T1 and T2*/
BinTree CombineTrees(BinTree T1, BinTree T2)
{
BinTree tmp; //如果T1与T2是相同的二项队列
if (T1->Element > T2->Element)
return CombineTrees(T2, T1);
T2->NextSibling = T1->LeftChild;
T1->LeftChild = T2;
if(T1 == T2)
{
tmp = malloc(sizeof(struct BinNode));
tmp->Element = T1->Element;
tmp->NextSibling = T1->LeftChild;
T1->LeftChild = tmp;
tmp->LeftChild = NULL;
}
return T1;
}