// binomialheap.h -bds 2016Mar
typedef int node;
#define MaxNodes 100000
#define NULL 0;

///////////////////////////////////////////////////////////////////
// node space and memory management functions shared by all binomial heaps
///////////////////////////////////////////////////////////////////
node parent[MaxNodes];
node firstchild[MaxNodes];
node sibling[MaxNodes];
int  keys[MaxNodes];
int  degree[MaxNodes];

// These access functions are assignable, eg p(x) = y.
node & p(node x) { return parent[x]; }
node & fc(node x) { return firstchild[x]; }
node & sib(node x) { return sibling[x]; }
int & key(node x) { return keys[x]; }
int & deg(node x) { return degree[x]; }

// Establish free list - This is done once.
for (i = 1; i < MaxNodes; ++i) sib(i) = i-1)
node free_list = MaxNodes-1;

node get_node() // equivalent to malloc or new. 
{	node x = free_list; 
	free_list = sib(free_list); 
	if (x == NULL) throw no_more_nodes_exception; 
	return x; 
}

void put_node(node x) // equivalent to free or delete
{	sib(x) = free_list; free_list = x; }

///////////////////////////////////////////////////////////////////
/////// Simple binomial heap representation ///////////////////////
///////////////////////////////////////////////////////////////////
/* Functions beginning with BH_ are implement the meldable heap API.
Those without the BH_ prefix are helper functions.
*/

/* Heap property for a tree: key(x) < key(y) for all nodes x of tree 
 and all y children of x. */

// root is used for nodes serving as root of a binomial tree with the heap property
typedef node root; 

// heap is used for nodes forming a sibling list of roots in strictly increasing degree order
typedef node heap; 

heap BH_init() { return NULL; }

heap BH_insert(heap h, Key k) {
	root x = get_node(); // new, from free_list
    p(x) = sib(x) = child(x) = NULL;
	key(x) = k; deg(x) = 0;

	return insert(h,x);
}

heap insert(heap h, root x){ // recursive helper for BH_insert
// Input: x is root of binomial tree, has sib(x) == NULL
// Output: h is modified to incorporate x. The resulting list is returned.
	if (h == NULL) 
		return x;
	if (deg(h) < deg(x)) 
		{ sib(h) = insert(sib(h), x); return h; }
	else if (deg(h) > deg(x)) 
		{ sib(x) = h; return x; }
	else /* deg(h) == deg(x) */
        { return insert(sib(h), link(h,x)); }
} // Cost is Theta(length of h).

void link(root h, root x) {// Make x the parent of y, preserving heap property.
// h may be sib(a) for some a. 
// The combined result must still be sib(a).
	if (key(h) < key(x)) {	
		p(x) = h; deg(h) = deg(h)+1; sib(x) = fc(h); fc(h) = x; 
		return h;
	} else {	
		p(h) = x; deg(x) = deg(x)+1; sib(h) = fc(x); fc(x) = h; 
		return x;
	}
} // Cost is Theta(1).

heap BH_union(heap a, heap b) {   
// In: a and b are heaps (sib lists that are strictly increasing by degree).
// Out: result is a heap combining every node in a and b.
	node c = merge(a,b); 
	/* c has nondecreasing degrees 
	   with each degree occurring zero, one, or two times in a row.*/
	node d = consolidate(c);
	return d;
} // Cost is cost of merge plus cost of consolidate.

heap merge(heap a, heap b) {
// In: a and b are in strictly increasing order
// Output is in nondecreasing order. It is not strictly a heap in that  
// for some degrees it may have 2 roots in a row of that degree. 
	if (a == NULL) return b;
	if (b == NULL) return a;
	if (deg(a) < deg(b)) {
		sib(a) = merge(sib(a), b);
		return a;
	} else { // deg(a) >= deg(b)
		sib(b) = merge(a, sib(b));
		return b;
	}
} // Cost of merge is O(m+n), Omega(min(m,n)), 
  // for m,n = lengths of a,b respectively

node consolidate(node a) {
// In: a is in nondecreasing degree order, at most 2 at any degree.
// However, the first root degree may occur 3 times, because of a "carry".
// Out: eliminate duplication (trees of same degree get linked).
	if (a == NULL or sib(a) == NULL) 
		return a;
	if (deg(a) < deg(sib(a))) {	 
		sib(a) = consolidate (sib(a)); 
	} else { // deg(x) == deg(sib(x))
	 	node c = sib(sib(a));
		if (c == NULL or deg(c) > deg(a)) { 	
			a = link(a, sib(a)); 
			return consolidate(a);
		} else { // keep first of the 3 at this degree, consolidate other 2.
			sib(a) = consolidate(sib(a)); 
			return a;
		}
	}
} // Cost is Theta(length of a as a sibling list)

///// Accessing and extracting the min (highest priority item) ////////

Key BH_min(heap h) { return key(min_root(h)); }

root min_root(heap h) {	
// In: non-null heap h
// Out: root of the tree in h having the least key.
	if (sib(h) == NULL) 
		return h;
	x = min_root(sib(h));
	if (key(x) < key(h)) 
		return x 
	else 
		return h;
} // Cost is Theta(length of h)

Key BH_extractMin(heap h) 
{	root x = min_root(h);
	Key k = key(x);
	h = remove(x, h);
	heap b = reverse(fc(x), NULL);
	BH_union(h, b);
	put_node(x); // return x to free_list
	return k;
}

heap remove(root x, heap h) {
	if (x == h) return sib(h);
	sib(h) = remove(x, sib(h)); 
	return h;
}

heap reverse(heap a, heap b) {
	//In: nodes of a ito be added, in reverse order, to front of nodes of b 
	//Out; first node of result
	if (a == NULL) return b;
	heap x = sib(a);
	sib(a) = b;
	return reverse(x, a);
}
