private BinomialHeapNode reverse(BinomialHeapNode sibl) {
   BinomialHeapNode ret;
   if (sibling != null) ret = sibling.reverse(this);
   else ret = this;
   sibling = sibl;
   return ret;
 }
  // 3. Unite two binomial heaps
  // helper procedure
  private void merge(BinomialHeapNode binHeap) {
    BinomialHeapNode temp1 = Nodes, temp2 = binHeap;
    while ((temp1 != null) && (temp2 != null)) {
      if (temp1.degree == temp2.degree) {
        gen(1, temp1, temp2);
        BinomialHeapNode tmp = temp2;
        temp2 = temp2.sibling;
        tmp.sibling = temp1.sibling;
        temp1.sibling = tmp;
        temp1 = tmp.sibling;
      } else {
        if (temp1.degree < temp2.degree) {
          if ((temp1.sibling == null) || (temp1.sibling.degree > temp2.degree)) {
            gen(2, temp1, temp2);
            BinomialHeapNode tmp = temp2;
            temp2 = temp2.sibling;
            tmp.sibling = temp1.sibling;
            temp1.sibling = tmp;
            temp1 = tmp.sibling;
          } else {
            gen(3, temp1, temp2);
            temp1 = temp1.sibling;
          }
        } else {
          BinomialHeapNode tmp = temp1;
          temp1 = temp2;
          temp2 = temp2.sibling;
          temp1.sibling = tmp;
          if (tmp == Nodes) {
            gen(4, temp1, temp2);
            Nodes = temp1;
          } else {
            gen(5, temp1, temp2);
          }
        }
      }
    }

    if (temp1 == null) {
      temp1 = Nodes;
      while (temp1.sibling != null) {
        gen(6, temp1, temp2);
        temp1 = temp1.sibling;
      }
      temp1.sibling = temp2;
    } else {
      gen(7, temp1, temp2);
    }
  }
  // 6. Decrease a key value
  public void decreaseKeyVariable(int old_value, int new_value) {
    BinomialHeapNode temp = Nodes.findANodeWithKey(old_value);
    if (temp == null) return;
    temp.key = new_value;
    BinomialHeapNode tempParent = temp.parent;

    while ((tempParent != null) && (temp.key < tempParent.key)) {
      int z = temp.key;
      gen(21, temp, tempParent);
      temp.key = tempParent.key;
      tempParent.key = z;

      temp = tempParent;
      tempParent = tempParent.parent;
    }
  }
 private int getSize() {
   return (1
       + ((child == null) ? 0 : child.getSize())
       + ((sibling == null) ? 0 : sibling.getSize()));
 }
 // 7. Delete a node with a certain key
 public void delete(int value) {
   if ((Nodes != null) && (Nodes.findANodeWithKey(value) != null)) {
     decreaseKeyVariable(value, findMinimum() - 1);
     extractMin();
   }
 }
  // 5. Extract the node with the minimum key
  public int extractMin() {
    if (Nodes == null) return -1;

    BinomialHeapNode temp = Nodes, prevTemp = null;
    BinomialHeapNode minNode = Nodes.findMinNode();
    while (temp.key != minNode.key) {
      gen(13, temp, prevTemp);
      prevTemp = temp;
      temp = temp.sibling;
    }

    if (prevTemp == null) {
      gen(14, temp, prevTemp);
      Nodes = temp.sibling;
    } else {
      gen(15, temp, prevTemp);
      prevTemp.sibling = temp.sibling;
    }
    temp = temp.child;
    BinomialHeapNode fakeNode = temp;
    while (temp != null) {
      gen(16, temp, prevTemp);
      temp.parent = null;
      temp = temp.sibling;
    }

    if ((Nodes == null) && (fakeNode == null)) {
      gen(17, temp, prevTemp);
      size = 0;
    } else {
      if ((Nodes == null) && (fakeNode != null)) {
        gen(18, Nodes, fakeNode);
        Nodes = fakeNode.reverse(null);
        size = Nodes.getSize();
      } else {
        if ((Nodes != null) && (fakeNode == null)) {
          gen(19, Nodes, fakeNode);
          size = Nodes.getSize();
        } else {
          gen(20, Nodes, fakeNode);
          unionNodes(fakeNode.reverse(null));
          size = Nodes.getSize();
        }
      }
    }

    return minNode.key;
  }
  // another helper procedure
  private void unionNodes(BinomialHeapNode binHeap) {
    merge(binHeap);

    BinomialHeapNode prevTemp = null, temp = Nodes, nextTemp = Nodes.sibling;

    while (nextTemp != null) {
      if ((temp.degree != nextTemp.degree)
          || ((nextTemp.sibling != null) && (nextTemp.sibling.degree == temp.degree))) {
        gen(8, temp, nextTemp);
        prevTemp = temp;
        temp = nextTemp;
      } else {
        if (temp.key <= nextTemp.key) {
          gen(9, temp, nextTemp);
          temp.sibling = nextTemp.sibling;
          nextTemp.parent = temp;
          nextTemp.sibling = temp.child;
          temp.child = nextTemp;
          temp.degree++;
        } else {
          if (prevTemp == null) {
            gen(10, temp, nextTemp);
            Nodes = nextTemp;
          } else {
            gen(11, temp, nextTemp);
            prevTemp.sibling = nextTemp;
          }
          temp.parent = nextTemp;
          temp.sibling = nextTemp.child;
          nextTemp.child = temp;
          nextTemp.degree++;
          temp = nextTemp;
        }
      }
      gen(12, temp, nextTemp);

      nextTemp = temp.sibling;
    }
  }
 // 2. Find the minimum key
 public int findMinimum() {
   return Nodes.findMinNode().key;
 }