Nov 4 20:34 1997 binheap.h Page 1 typedef int ElementType; /* START: fig6_4.txt */ #ifndef _BinHeap_H #define _BinHeap_H struct HeapStruct; typedef struct HeapStruct *PriorityQueue; PriorityQueue Initialize( int MaxElements ); void Destroy( PriorityQueue H ); void MakeEmpty( PriorityQueue H ); void Insert( ElementType X, PriorityQueue H ); ElementType DeleteMin( PriorityQueue H ); ElementType FindMin( PriorityQueue H ); int IsEmpty( PriorityQueue H ); int IsFull( PriorityQueue H ); #endif /* END */ Aug 12 15:27 1996 binheap.c Page 1 #include "binheap.h" #include "fatal.h" #include #define MinPQSize (10) #define MinData (-32767) struct HeapStruct { int Capacity; int Size; ElementType *Elements; }; /* START: fig6_0.txt */ PriorityQueue Initialize( int MaxElements ) { PriorityQueue H; /* 1*/ if( MaxElements < MinPQSize ) /* 2*/ Error( "Priority queue size is too small" ); /* 3*/ H = malloc( sizeof( struct HeapStruct ) ); /* 4*/ if( H ==NULL ) /* 5*/ FatalError( "Out of space!!!" ); /* Allocate the array plus one extra for sentinel */ /* 6*/ H->Elements = malloc( ( MaxElements + 1 ) * sizeof( ElementType ) ); /* 7*/ if( H->Elements == NULL ) /* 8*/ FatalError( "Out of space!!!" ); /* 9*/ H->Capacity = MaxElements; /*10*/ H->Size = 0; /*11*/ H->Elements[ 0 ] = MinData; /*12*/ return H; } /* END */ void MakeEmpty( PriorityQueue H ) { H->Size = 0; } /* START: fig6_8.txt */ /* H->Element[ 0 ] is a sentinel */ void Insert( ElementType X, PriorityQueue H ) { int i; if( IsFull( H ) ) Aug 12 15:27 1996 binheap.c Page 2 { Error( "Priority queue is full" ); return; } for( i = ++H->Size; H->Elements[ i / 2 ] > X; i /= 2 ) H->Elements[ i ] = H->Elements[ i / 2 ]; H->Elements[ i ] = X; } /* END */ /* START: fig6_12.txt */ ElementType DeleteMin( PriorityQueue H ) { int i, Child; ElementType MinElement, LastElement; /* 1*/ if( IsEmpty( H ) ) { /* 2*/ Error( "Priority queue is empty" ); /* 3*/ return H->Elements[ 0 ]; } /* 4*/ MinElement = H->Elements[ 1 ]; /* 5*/ LastElement = H->Elements[ H->Size-- ]; /* 6*/ for( i = 1; i * 2 <= H->Size; i = Child ) { /* Find smaller child */ /* 7*/ Child = i * 2; /* 8*/ if( Child != H->Size && H->Elements[ Child + 1 ] /* 9*/ < H->Elements[ Child ] ) /*10*/ Child++; /* Percolate one level */ /*11*/ if( LastElement > H->Elements[ Child ] ) /*12*/ H->Elements[ i ] = H->Elements[ Child ]; else /*13*/ break; } /*14*/ H->Elements[ i ] = LastElement; /*15*/ return MinElement; } /* END */ ElementType FindMin( PriorityQueue H ) { if( !IsEmpty( H ) ) return H->Elements[ 1 ]; Error( "Priority Queue is Empty" ); return H->Elements[ 0 ]; } int IsEmpty( PriorityQueue H ) Aug 12 15:27 1996 binheap.c Page 3 { return H->Size == 0; } int IsFull( PriorityQueue H ) { return H->Size == H->Capacity; } void Destroy( PriorityQueue H ) { free( H->Elements ); free( H ); } #if 0 /* START: fig6_14.txt */ for( i = N / 2; i > 0; i-- ) PercolateDown( i ); /* END */ #endif Aug 12 15:27 1996 testheap.c Page 1 #include "binheap.h" #include #define MaxSize (1000) main( ) { PriorityQueue H; int i, j; H = Initialize( MaxSize ); for( i=0, j=MaxSize/2; i struct TreeNode { ElementType Element; PriorityQueue Left; PriorityQueue Right; int Npl; }; PriorityQueue Initialize( void ) { return NULL; } static PriorityQueue Merge1( PriorityQueue H1, PriorityQueue H2 ); /* START: fig6_26.txt */ PriorityQueue Merge( PriorityQueue H1, PriorityQueue H2 ) { /* 1*/ if( H1 == NULL ) /* 2*/ return H2; /* 3*/ if( H2 == NULL ) /* 4*/ return H1; /* 5*/ if( H1->Element < H2->Element ) /* 6*/ return Merge1( H1, H2 ); else /* 7*/ return Merge1( H2, H1 ); } /* END */ void SwapChildren( PriorityQueue H ) { PriorityQueue Tmp; Tmp = H->Left; H->Left = H->Right; H->Right = Tmp; } /* START: fig6_27.txt */ static PriorityQueue Merge1( PriorityQueue H1, PriorityQueue H2 ) { /* 1*/ if( H1->Left == NULL ) /* Single node */ /* 2*/ H1->Left = H2; /* H1->Right is already NULL, H1->Npl is already 0 */ else { /* 3*/ H1->Right = Merge( H1->Right, H2 ); /* 4*/ if( H1->Left->Npl < H1->Right->Npl ) Aug 12 15:27 1996 leftheap.c Page 2 /* 5*/ SwapChildren( H1 ); /* 6*/ H1->Npl = H1->Right->Npl + 1; } /* 7*/ return H1; } /* END */ /* START: fig6_29.txt */ PriorityQueue Insert1( ElementType X, PriorityQueue H ) { PriorityQueue SingleNode; /* 1*/ SingleNode = malloc( sizeof( struct TreeNode ) ); /* 2*/ if( SingleNode == NULL ) /* 3*/ FatalError( "Out of space!!!" ); else { /* 4*/ SingleNode->Element = X; SingleNode->Npl = 0; /* 5*/ SingleNode->Left = SingleNode->Right = NULL; /* 6*/ H = Merge( SingleNode, H ); } /* 7*/ return H; } /* END */ /* START: fig6_30.txt */ /* DeleteMin1 returns the new tree; */ /* To get the minimum, use FindMin */ /* This is for convenience */ PriorityQueue DeleteMin1( PriorityQueue H ) { PriorityQueue LeftHeap, RightHeap; /* 1*/ if( IsEmpty( H ) ) { /* 2*/ Error( "Priority queue is empty" ); /* 3*/ return H; } /* 4*/ LeftHeap = H->Left; /* 5*/ RightHeap = H->Right; /* 6*/ free( H ); /* 7*/ return Merge( LeftHeap, RightHeap ); } /* END */ ElementType FindMin( PriorityQueue H ) { if( !IsEmpty( H ) ) Aug 12 15:27 1996 leftheap.c Page 3 return H->Element; Error( "Priority Queue is Empty" ); return 0; } int IsEmpty( PriorityQueue H ) { return H == NULL; } Aug 12 15:27 1996 testleft.c Page 1 #include "leftheap.h" #include #define MaxSize 5000 main( ) { PriorityQueue H; int i, j; H = Initialize( ); for( i=0, j=MaxSize/2; iCurrentSize = 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 Aug 12 15:27 1996 binomial.c Page 2 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 ); } /* START: fig6_56.txt */ 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; Aug 12 15:27 1996 binomial.c Page 3 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; } /* END */ 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 ) Aug 12 15:27 1996 binomial.c Page 4 { return H->CurrentSize == Capacity; } /* START: fig6_54.txt */ /* 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; } /* END */ /* START: fig6_55.txt */ /* 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; Aug 12 15:27 1996 binomial.c Page 5 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; } /* END */ Aug 12 15:27 1996 testbin.c Page 1 #include "binomial.h" #include #define MaxSize (12000) main( ) { BinQueue H; int i, j; ElementType AnItem; H = Initialize( ); for( i=0, j=MaxSize/2; i