0.1) 本文文字描述部分转自 数据结构与算法分析, 旨在理解 优先队列——二项队列(binominal queue) 的基础知识;
0.2) 本文核心的剖析思路均为原创(insert,merge和deleteMin的操作步骤图片示例), 源代码均为原创;
0.3) for original source code, please visit https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter6/p152_binominal_queue
1.0)Attention: 二项队列中不允许有高度相同的二项树存在该队列中;
1.1)problem+solution:
1.2)相关定义
对上图的分析(Analysis):
A1)二项树的性质:
A2)如果我们把堆序添加到二项树上, 并允许任意高度上最多有一颗二项树,那么我们能够用二项树的集合唯一地表示任意大小的优先队列;
2.1)合并操作(merge) (干货——合并操作的第一步就是查看是否有高度相同的二项树,如果有的话将它们merge)
Attention)
2.2)插入操作(insert) (干货——insert操作是merge操作的特例,而merge操作的第一步就是查看是否有高度相同的二项树,如果有的话将它们merge)
对上图的分析(Analysis):
2.3)删除最小值操作(deleteMin)
3.1)source code at a glance
Attention)二项队列的实现源代码用到了 儿子兄弟表示法;
#include "binominal_queue.h"
#define MINIMAL 10000
int minimal(BinominalQueue bq)
{
int capacity;
int i;
int minimal;
int miniIndex;
minimal = MINIMAL;
capacity = bq->capacity;
for(i=0; iif(bq->trees[i] && bq->trees[i]->value < minimal)
{
minimal = bq->trees[i]->value;
miniIndex = i;
}
}
return miniIndex;
}
// initialize the BinominalQueue with given capacity.
BinominalQueue init(int capacity)
{
BinominalQueue queue;
BinominalTree* trees;
int i;
queue = (BinominalQueue)malloc(sizeof(struct BinominalQueue));
if(!queue)
{
Error("failed init, for out of space !");
return queue;
}
queue->capacity = capacity;
trees = (BinominalTree*)malloc(capacity * sizeof(BinominalTree));
if(!trees)
{
Error("failed init, for out of space !");
return NULL;
}
queue->trees = trees;
for(i=0; iqueue->trees[i] = NULL;
}
return queue;
}
// attention: the root must be the left child of the binominal tree.
int getHeight(BinominalTree root)
{
int height;
if(root == NULL)
{
return 0;
}
height = 1;
while(root->nextSibling)
{
height++;
root = root->nextSibling;
}
return height;
}
// merge BinominalQueue bq2 into bq1.
void outerMerge(BinominalQueue bq1, BinominalQueue bq2)
{
int height;
int i;
for(i=0; icapacity; i++)
{
height = -1;
if(bq2->trees[i])
{
height = getHeight(bq2->trees[i]->leftChild);
// attention for the line above
// height = height(bq2->trees[i]->leftChild); not height = height(bq2->trees[i]);
merge(bq2->trees[i], height, bq1);
}
}
}
// merge tree h1 and h2 = bq->trees[height],
// who represents the new tree and old one respectively.
BinominalTree merge(BinominalTree h1, int height, BinominalQueue bq)
{
if(h1 == NULL)
{
return h1;
}
if(bq->trees[height] == NULL) // if the queue don't has the B0 tree.
{
bq->trees[height] = h1;
return bq->trees[height];
}
else // otherwise, compare the new tree's height with that of old one.
{
if(h1->value > bq->trees[height]->value) // the new should be treated as the parent of the old.
{
innerMerge(bq->trees[height], height, h1, bq);
}
else // the old should be treated as the parent of the new.
{
innerMerge(h1, height, bq->trees[height], bq);
}
}
return h1;
}
BinominalTree lastChild(BinominalTree root)
{
while(root->nextSibling)
{
root = root->nextSibling;
}
return root;
}
// merge tree h1 and h2 = bq->trees[height],
// who represents the new tree and old one respectively.
BinominalTree innerMerge(BinominalTree h1, int height, BinominalTree h2, BinominalQueue bq)
{
if(h1->leftChild == NULL)
{
h1->leftChild = h2;
}
else
{
lastChild(h1->leftChild)->nextSibling = h2;
// attention for the line above
// lastChild(h1->leftChild)->nextSibling = h2 not lastChild(h1)->nextSibling = h2
}
height++;
bq->trees[height-1] = NULL;
merge(h1, height, bq);
return h1;
}
// insert an element with value into the priority queue.
void insert(ElementType value, BinominalQueue bq)
{
TreeNode node;
node = (TreeNode)malloc(sizeof(struct TreeNode));
if(!node)
{
Error("failed inserting, for out of space !");
return ;
}
node->leftChild= NULL;
node->nextSibling = NULL;
node->value = value;
merge(node, 0, bq);
}
// analog print node values in the binominal tree, which involves preorder traversal.
void printPreorderChildSibling(int depth, BinominalTree root)
{
int i;
if(root) {
for(i = 0; i < depth; i++)
printf(" ");
printf("%d\n", root->value);
printPreorderChildSibling(depth + 1, root->leftChild);
printPreorderChildSibling(depth, root->nextSibling);
}
else
{
for(i = 0; i < depth; i++)
printf(" ");
printf("NULL\n");
}
}
// print Binominal Queue bq
void printBinominalQueue(BinominalQueue bq)
{
int i;
for(i=0; icapacity; i++)
{
printf("bq[%d] = \n", i);
printPreorderChildSibling(1, bq->trees[i]);
}
}
void deleteMin(BinominalQueue bq)
{
int i;
BinominalTree minitree;
BinominalTree sibling;
i = minimal(bq);
minitree = bq->trees[i]->leftChild; //minitree->value=51
free(bq->trees[i]);
bq->trees[i] = NULL;
while(minitree)
{
sibling = minitree->nextSibling;
minitree->nextSibling = NULL;
merge(minitree, getHeight(minitree->leftChild), bq);
minitree = sibling;
}
}
3.2) printing results
![]() |
![]() |
![]() |
![]() |
![]() |