using
System;
using
System.Collections.Generic;
using
System.Linq;
class
Node {
public
int
Value;
public
Node Parent;
public
List<Node> Children;
public
int
Degree;
public
bool
Marked;
public
Node(
int
val)
{
Value = val;
Parent =
null
;
Children =
new
List<Node>();
Degree = 0;
Marked =
false
;
}
}
class
BinomialHeap {
public
List<Node> Trees;
public
Node MinNode;
public
int
Count;
public
BinomialHeap()
{
MinNode =
null
;
Count = 0;
Trees =
new
List<Node>();
}
public
bool
IsEmpty() {
return
MinNode ==
null
; }
public
void
Insert(
int
value)
{
Node node =
new
Node(value);
BinomialHeap heap =
new
BinomialHeap();
heap.Trees.Add(node);
Merge(heap);
}
public
int
GetMin() {
return
MinNode.Value; }
public
int
ExtractMin()
{
Node minNode = MinNode;
Trees.Remove(minNode);
BinomialHeap heap =
new
BinomialHeap();
heap.Trees = minNode.Children;
Merge(heap);
FindMin();
Count -= 1;
return
minNode.Value;
}
public
void
Merge(BinomialHeap otherHeap)
{
Trees.AddRange(otherHeap.Trees);
Count += otherHeap.Count;
FindMin();
}
private
void
FindMin()
{
MinNode =
null
;
foreach
(Node tree
in
Trees)
{
if
(MinNode ==
null
|| tree.Value < MinNode.Value) {
MinNode = tree;
}
}
}
public
void
DecreaseKey(Node node,
int
newValue)
{
if
(newValue > node.Value) {
throw
new
ArgumentException(
"New value is greater than the current value"
);
}
node.Value = newValue;
BubbleUp(node);
}
public
void
DeleteNode(Node node)
{
DecreaseKey(node,
int
.MinValue);
ExtractMin();
}
private
void
BubbleUp(Node node)
{
Node parent = node.Parent;
while
(parent !=
null
&& node.Value < parent.Value) {
Swap(
ref
node.Value,
ref
parent.Value);
node = parent;
parent = node.Parent;
}
}
private
void
Link(Node tree1, Node tree2)
{
if
(tree1.Value > tree2.Value) {
Swap(
ref
tree1,
ref
tree2);
}
tree2.Parent = tree1;
tree1.Children.Add(tree2);
tree1.Degree += 1;
}
private
void
Consolidate()
{
int
maxDegree
= (
int
)Math.Floor(Math.Log2(Count)) + 1;
List<Node> degreeToTree =
new
List<Node>(
Enumerable.Repeat<Node>(
null
, maxDegree + 1));
while
(Trees.Any()) {
Node current = Trees[0];
Trees.Remove(current);
int
degree = current.Degree;
while
(degreeToTree[degree] !=
null
) {
Node other = degreeToTree[degree];
degreeToTree[degree] =
null
;
if
(current.Value < other.Value) {
Link(current, other);
}
else
{
Link(other, current);
current = other;
}
degree++;
}
degreeToTree[degree] = current;
}
MinNode =
null
;
Trees.Clear();
foreach
(Node tree
in
degreeToTree)
{
if
(tree !=
null
) {
Trees.Add(tree);
if
(MinNode ==
null
|| tree.Value < MinNode.Value) {
MinNode = tree;
}
}
}
}
public
int
Size() {
return
Count; }
private
void
Swap(
ref
int
a,
ref
int
b)
{
int
temp = a;
a = b;
b = temp;
}
}