// decrease_key and delete for binomial heaps, -bds 03Oct, // Reference: CLR chapter 19 /* We add the mergable heap functions: * Binomial_Heap_Decrease_Key() and Binomial_Heap_Delete(). * * To do this the Key class must provide additional functionality * as described below. * * Decrease_Key() runs in worst case time Theta(lg(n)). * Delete() takes amortized time O(lg(n)). */ #ifndef __BINOMIALHEAPD_H #define __BINOMIALHEAPD_H #include "binomialHeapA.h" // defines binomialHeap's other functions. /******************************** We have been assuming of Keys only that operator < exists and defines a strict weak ordering among Keys. In practice the key might be a pointer to a user record of some kind and operator< would be defined to compare on a specific value within that record perhaps. Or the key might be a pair consisting of that specific value and a pointer to the rest of the associated record, with operator< basing it's comparision on the first field of the pair. In either case the user is not concerned with where the key resides within the heap. The user inserts the key and ultimately gets it back with a Minimum() call. Thats all there is to it. When Decrease_Key is also to be provided, however, there must be a way for the user and the heap to share knowledge of where an arbitrary key is at any given time. When the user wants to say "I now decrease key k", how shall the heap find the node containing k and take the appropriate action? How shall the user know where moved keys have gone? One possibility is to have the heap maintain a hash table indexed by keys and containing a pointer to the node currently containing each key. Actions to keep the hash table up to date as keys are moved would take O(1) expected time. In CLR, it is assumed that the objects are numbers in the range 1..n (for some n) which serve as indices into parallel arrays. thus key[x] is an array lookup. Also tree[x] could be a direct table in this case, giving the location of the (sub)tree of which x is the root key. This gives simple O(1) cost each time a table entry must be accessed. However, it is not always the case that it is convenient to have the objects be represented by indices (which are used in a number of arrays representing the "fields" of the object). Let us take a more object oriented approach. Let each key k have a function nodePtr(k) which returns an assignable reference to an iterator within k itself. Thus Decrease_Key() can use the nodePtr(k) to find the node and can also fix the nodePtr(k)'s when moving keys around. ********************************/ template inline void Binomial_Heap_Decrease_Key( heap& H, Key& k ) /* We assume the user has already modified k so that now it may * be less than it's parent in the heap. Our job is to restore * heap properties. Worst case cost is Theta(lg(n)). */ { treePtr x = nodePtr(k); treePtr p = parent(x); while ( p != NULL && *x < *p ) { swap( key(*x), key(p) ); nodePtr(k) = p; nodePtr( key(*x) ) = x; } } template inline void Binomial_Heap_Delete( heap& H, Key& k ) /* We assume the user has already modified k so that now it is less * than Minimum( H ). Our job is to remove it and restore heap properties. */ { Binomial_Heap_Decrease_Key( H, k ); Binomial_heap_Extract_Min( H ); } #endif