Structure

  • A binomial queue is not one heap-ordered tree, but rather a collection of heap-ordered trees, known as a forest. Each heap-ordered tree is a binomial tree.
  • A binomial tree of height 0 is a one-node tree.
  • A binomial tree, BkB_k, of height kk is formed by attaching a binomial tree,Bk1B_{k – 1}, to the root of another binomial tree, Bk1B_{k – 1}.
image-20210328211738432
  • BkB_k consists of a root with kk children, which are B0,B1,,Bk1B_0,B_1,\cdots,B_{k-1}.

  • BkB_k has exactly 2k2^k nodes.

  • The number of nodes at depth dd is CkdC_k^d, which is binomial coefficient.

  • A priority queue of any size can be uniquely represented by a collection of binomial trees.

    image-20210328212505044

Operations

FindMin

  • The minimum key is in one of the roots.
  • There are at most logN\lceil \log N\rceil roots, hence Tp=O(logN)T_p=O(\log N).

Note: We can remember the minimum and update whenever it is changed. Then this operation will take O(1).

Merge

image-20210328215006412

image-20210328215016723

image-20210328215054012

  • Tp=O(logN)T_p=O(\log N), but must keep the trees in the binomial queue sorted by height.

Insert

  • a special case for merging

Note:

  • If the smallest nonexistent binomial tree is BiB_i , then Tp=Const(i+1)T_p = \text{Const} \cdot(i + 1).
  • Performing NN Inserts on an initially empty binomial queue will take O(N)O(N) worst-case time. Hence the average time is constant.

DeleteMin

  • Step 1: FindMin in BkB_k

    image-20210328220334030

    Tp=O(logN)T_p=O(\log N)

  • Step 2: Remove BkB_k from HH

    image-20210328220410583

    Tp=O(1)T_p=O(1)

  • Step 3: Remove root from BkB_k

    image-20210328220439904

    Tp=O(logN)T_p=O(\log N)

  • Step 4: Merge(H,HH',H'')

    image-20210328220522412

    Tp=O(logN)T_p=O(\log N)

Implementation

  • Binomial queue = array of binomial trees
Operation Property Solution
DeleteMin Find all the subtrees quickly Left-child-next-sibling with linked lists
Merge The children are ordered by their sizes The next tree will be the largest. Hence maintain the subtrees in decreasing sizes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct BinNode *Position;
typedef struct Collection *BinQueue;
typedef struct BinNode *BinTree; /*missing from p.176*/

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

struct Collection
{
int CurrentSize; /*total number of nodes*/
BinTree TheTrees[ MaxTrees ];
} ;

Combine trees

1
2
3
4
5
6
7
8
9
10
BinTree CombineTrees( BinTree T1, BinTree T2 ) /*merge equal-sized T1 and T2*/
{
if ( T1->Element > T2->Element ) /*attach the larger one to the smaller one*/
return CombineTrees( T2, T1 );

/*insert T2 to the front of the children list of T1*/
T2->NextSibling = T1->LeftChild;
T1->LeftChild = T2;
return T1;
}
image-20210329125858668 $$ T_p=O(1) $$

Merge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
BinQueue Merge( BinQueue H1, BinQueue H2 )
{
BinTree T1, T2, Carry = NULL;
int i, j;
if ( H1->CurrentSize+H2->CurrentSize > Capacity )
ErrorMessage();
H1->CurrentSize += H2->CurrentSize;
for ( i = 0, j = 1; j <= H1->CurrentSize; i++, j *= 2 )
/*i and j are the index and size of the tree separately*/
{
T1 = H1->TheTrees[i]; T2 = H2->TheTrees[i]; /*current trees*/
switch( 4*!!Carry + 2*!!T2 + !!T1 ) /*assign each digit to a tree*/
{
case 0: /*000*/
case 1: /*001*/
break;
case 2: /*010*/
H1->TheTrees[i] = T2;
H2->TheTrees[i] = NULL;
break;
case 4: /*100*/
H1->TheTrees[i] = Carry;
Carry = NULL;
break;
case 3: /*011*/
Carry = CombineTrees( T1, T2 );
H1->TheTrees[i] = H2->TheTrees[i] = NULL;
break;
case 5: /*101*/
Carry = CombineTrees( T1, Carry );
H1->TheTrees[i] = NULL;
break;
case 6: /*110*/
Carry = CombineTrees( T2, Carry );
H2->TheTrees[i] = NULL;
break;
case 7: /*111*/
H1->TheTrees[i] = Carry;
Carry = CombineTrees( T1, T2 );
H2->TheTrees[i] = NULL;
break;
} /*end switch*/
} /*end for-loop*/
return H1;
}

DeleteMin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ElementType DeleteMin( BinQueue H )
{
BinQueue DeletedQueue;
Position DeletedTree, OldRoot;
ElementType MinItem = Infinity; /*the minimum item to be returned*/
int i, j, MinTree; /*MinTree is the index of the tree with the minimum item*/

if ( IsEmpty(H) )
{
PrintErrorMessage();
return –Infinity;
}

for ( i = 0; i < MaxTrees; i++) /*Step 1: find the minimum item*/
{
if( H->TheTrees[i] && H->TheTrees[i]->Element < MinItem )
{
MinItem = H->TheTrees[i]->Element;
MinTree = i;
} /*end if*/
} /*end for-i-loop*/
DeletedTree = H->TheTrees[ MinTree ];
H->TheTrees[ MinTree ] = NULL; /*Step 2: remove the MinTree from H => H’*/
OldRoot = DeletedTree; /*Step 3.1: remove the root*/
DeletedTree = DeletedTree->LeftChild;
free(OldRoot);
DeletedQueue = Initialize(); /*Step 3.2: create H”*/
DeletedQueue->CurrentSize = ( 1<<MinTree ) – 1; /*2^MinTree – 1*/
for ( j = MinTree–1; j >= 0; j–– )
{
DeletedQueue->TheTrees[j] = DeletedTree;
DeletedTree = DeletedTree->NextSibling;
DeletedQueue->TheTrees[j]->NextSibling = NULL;
} /*end for-j-loop*/
H->CurrentSize –= DeletedQueue->CurrentSize+1;
H = Merge( H, DeletedQueue ); /*Step 4: merge H’ and H”*/
return MinItem;
}

Amortized Analysis

  • The worst case time for each insertion is O(logN)O(\log N).
  • A binomial queue of NN elements can be built by NN successive insertions in O(N)O(N) time.

Aggregate method

image-20210329135052487
  • Total steps = NN
  • Total links = N(14+218+3116+)=O(N)N(\frac14+2\cdot\frac18+3\cdot\frac1{16}+\cdots)=O(N)

Potential method

  • An insertion that costs cc units results in a net increase of 2c2 – c trees in the forest.

  • CiC_i = cost of the iith insertion

  • Φi\Phi_i = number of trees after thr iith insertion(Φ0=0\Phi_0=0)

  • Ci+(ΦiΦi1)=2C_i+(\Phi_i-\Phi_{i-1})=2 for all i=1,2,,Ni=1,2,\cdots,N

  • Add all the equations up:

    i=1NCi+ΦiΦ0=2N\sum^N_{i=1}C_i+\Phi_i-\Phi_0=2N

    i=1NCi=2NΦN2N=O(N)\sum^N_{i=1}C_i=2N-\Phi_N\leq 2N=O(N)

  • Tworst=O(logN)T_{worst}=O(\log N), but Tamortized=2T_{amortized}=2