Hello, everyone!:) I am new to Daniweb and I would like a little help in implementing Binomial Heap subroutines in C, especially insertion in Heap. For my application it is necessary to implement max-heaps(i.e., roots storing the maximum value) in stead of min-heaps(i.e., root storing minimum value) in ANSI C. I have written a few subroutines - but things are not working properly. I will explain my codes here with code snippet and my problem.

struct _tnode{
	int key;//a field key for its key
	int degree;/*a field degree for the number of children -or for the degree of the tree rooted at the node*/
	int u; //to store the no. of entry in the graphic sequence
	struct _tnode *child;//a pointer child , which points to the leftmost-child
	struct _tnode *sibling;//a pointer sibling, which points to the right-sibling
	struct _tnode *p;//a pointer p, which points to the parent
	};
	
typedef struct _tnode node;

struct _theap{
	node *head;//only a pointer to point to a node, next nodes would be the siblings
	};
typedef struct _theap heap;

this was the definition of Tree nodes and heap structure. the field "degree" stores the degree of the binomial tree rooted at current node, "key" stores the value, "u" is satelite data.
I used initializeHeap() to initiate a Heap using malloc with the head pointer being NULL. Now there are some subroutines like binomialHeapFindMaximum(heap *H) which returns pointer to a root node in the heap which has the maximum key value. Now there is mergeBinomialHeap() which merges two binomial heaps H1 and H2 such that trees of same degree(s) fall next to each other. Obviously, the heap structure, returned by mergeBinomialHeap is modified by the calling subroutine unionBinomialHeap() which uses the previous routine, modifies the returned Heap and returns a proper heap structure. There is one more helper subroutine binomialTreeLink() that takes two root nodes of two trees of same degree as input, makes the first one second tree's left subtree. I am providing codes for these three subroutines here.

//this function blindly merges two binomial heaps into one binomial heap, with placing trees of same degrees next to each other
//this is more like the "MERGE" subroutine in MergeSort//
//it is a helper subroutine to the union subroutine - the heap returned is not a 
//proper binomial heap.
heap* mergeBinomialHeap(heap* H1, heap* H2){
    heap* H = initializeHeap();//new heap initialized to hold the merged H1 & H2
    node* P= H->head ;
    node* P1 ;
    node* P2 ;
    P1 = H1->head;
    P2 = H2->head;
    
    //if both are empty heaps, return empty heap.
    if((P1==NULL) && (P2==NULL)){
	    return H;
	    }
	 
	 //if one of them is empty heap, return the other
	 if(((P1==NULL) && (P2!=NULL))||((P1!=NULL) && (P2==NULL))){
		 if(P1==NULL) return H2;
		 else return H1;
		 }
	
	//if none of them is empty heap, merge properly and return
	if((P1->degree)<(P2->degree)){
		P=P1;
		P1=P1->sibling;
		}
	else{
		P=P2;
		P2= P2->sibling;
		}
	H->head = P; /*after first node chosen by P from P1 and P2, make H->head point to it*/
	
	//now fill up the rest of the new heap
	while((P1!=NULL) && (P2!=NULL)){
		if((P1->degree)<(P2->degree)){
			P->sibling = P1;
			P1=P1->sibling;
			}
		else{
			P->sibling = P2;
			P2=P2->sibling;
			}
		}
	//one of P1 or P2 is NULL, so fill the trees from other heap
	if(P1==NULL){
		while(P2!=NULL){
			P->sibling = P2;
			P2 = P2->sibling;
			}
		}
	if(P2==NULL){
		while(P1!=NULL){
			P->sibling = P1;
			P1=P1->sibling;
			}
		}
	//end the new heap properly
	P->sibling = NULL;
	//printf("Binomial heaps merged\n");
   return H;
}


/*this function merges two heaps using mergeBinomialHeap() and modifies it to a proper binomial heap*/
heap* unionBinomialHeap(heap* H1, heap* H2){
    heap* H =initializeHeap();
    H = mergeBinomialHeap(H1,H2);
    if(H->head== NULL)
        return H;
    //printf("H not empty\n");
    node* prev_x = NULL;
    node* x = H->head;
    node *next_x = x->sibling;
    
    while(next_x !=NULL){
        if((x->degree != next_x->degree) || (next_x->sibling != NULL && (next_x->sibling)->degree == x->degree)){
            prev_x = x;//case 1 and 2
            x= next_x;
        }
        else if(x->key >= next_x->key){//this inequality sign is revered, as it is max-heap
            x->sibling = next_x->sibling;//case 3
            binomialTreeLink(next_x, x);
        }
        else {
	        if(prev_x== NULL){
             H->head = next_x;
           }
           else{
             prev_x->sibling = next_x;
           }
           binomialTreeLink(x,next_x);
           x= next_x;
           }
         
         next_x = x->sibling;//this operation is needed for all cases - so done at the end of the loop          
        }
       //printf("union binomial heap done\n");
      return H;  
        
   }



//calling function should check y->key < z->key, because this function makes z the //parent of new tree
void binomialTreeLink(node* y, node* z){//used to merge two binomial trees of same order
	y->p = z;                           //two root nodes are passed by pointers
	y->sibling = z->child;              
	z->child = y;
	z->degree +=1;
	}

When I am trying to use these subroutines from some calling functions, the problem, after a lots of debugging attempt, seems to me is that whenever I am using these subroutines to insert a new node in a heap - the previous nodes are getting deleted!! The insertNode subroutine is as follows:

//Inserts a node into the heap
//make a binomial heap with a tree of degree 0 with the node and 
//merge it with the Heap we need to insert the node in 
heap* binomialHeapInsert(heap* H, node* x){
	heap* h = initializeHeap();
	h->head = x;
	//printf("inside binomial heapInsert\n");
	//merge the single node with the heap
	H = unionBinomialHeap(H,h);
	return H;
	}

the calling subroutine which uses insertNode, first defines a Node pointer x, allocate space for it, makes proper modifications to its fields - finally calls this insertNode subroutine and tries to insert it. Now, as I have already said, something is deleting the previous nodes from the heap H and keeping only the current node being inserted. :( My guess is binomialTreeLink function is not working properly. Can anyone point out any mistake in these function? Any help would be greatly appreciated. Thanks in advance :)

Dani AI

Generated

Diagnosis and targeted fixes for the “previous nodes disappear after insert” symptom (for )

The behavior described matches a classic bug in the merge stage: when building the merged root-list the tail pointer is never advanced. Each time the code sets P->sibling = <chosen node> but does not do P = P->sibling; immediately afterward, so the same P->sibling slot gets overwritten repeatedly and earlier nodes become unreachable. Adding that single advancement in both the main two-list loop and the “append remaining nodes” loops will restore a correct linked list of roots.

Other practical fixes and sanity checks

  • Ensure every newly-created singleton node used for insertion is fully initialized (parent, child, sibling, degree). Example:

    x->p = x->child = x->sibling = NULL;
    x->degree = 0;

    Not initializing those pointers can produce exactly the loss/overwrite symptoms seen during subsequent merges.

  • Confirm unionBinomialHeap follows the CLRS pattern for max-heaps (your reversed comparison looks correct). Leave the next_x = x->sibling update at the end of the loop; if x or next_x is NULL the loop should exit cleanly.

Debugging checklist (short)

  • Print the merged root list immediately after mergeBinomialHeap and before unionBinomialHeap to verify all roots are present. For example:
    for (node *t = H->head; t; t = t->sibling)
    printf("root %p key=%d deg=%d sib=%p child=%p\n", (void*)t, t->key, t->degree, (void*)t->sibling, (void*)t->child);
  • Run Valgrind or a memory checker for invalid reads/writes and to catch accidental overwrites or use-after-free.
  • Avoid returning a mix of newly allocated heap structures and old ones (your merge sometimes returns H1/H2 directly); that can cause leaks and confusing ownership semantics—either return a consistently allocated heap or document ownership clearly.

Note on alternatives: ’s idea of using an array of roots changes merge complexity and is valid for other optimizations, but for the pointer-based approach the missing P = P->sibling; and uninitialized node fields are the primary causes of the insertion problem.

I optimized a Binomial min heap in c++, great for low costs when you discard the heap not empty because you have your spanning tree or shortest route. I changed the root to an array for fast merge.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.