二项堆
(binomial heap)是一种类似于二叉堆的堆结构。二项堆是指满足以下性质的二项树的集合,每一棵堆序树都是由约束的形式,叫做二项树。与二叉堆相比,其优势是可以快速合并两个堆,因此它属于可合并堆(mergeable heap)抽象数据类型的一种。
二项堆属性:
在一个高度为K的二项树中:
1. 根节点有K个儿子
2.树有个节点
3. 树的高度为K
4. 二项树子树由一个带有儿子
、
、、、
的根组成。
5 .每棵二项树都满足最小堆性质,即结点关键字大于等于其父结点的值
6 .不能有两棵或以上的二项树有相同度数(包括度数为0)。换句话说,具有度数k的二项树有0个或1个。
二项树
度数为0的二项树只包含一个结点。
度数为k的二项树有一个根结点,根结点下有个子女,每个子女分别是度数分别为
的二项树的根。
度为0的二项树
度为1的二项树
度为2的二项树
度为3的二项树
代码:
二项堆节点
class BinomialHeapNode
{
int key, degree;
BinomialHeapNode parent;
BinomialHeapNode sibling;
BinomialHeapNode child;
/* Constructor */
public BinomialHeapNode(int k)
{
key = k;
degree = 0;
parent = null;
sibling = null;
child = null;
}
/* Function reverse */
public BinomialHeapNode reverse(BinomialHeapNode sibl)
{
BinomialHeapNode ret;
if (sibling != null)
ret = sibling.reverse(this);
else
ret = this;
sibling = sibl;
return ret;
}
/* Function to find min node */
public BinomialHeapNode findMinNode()
{
BinomialHeapNode x = this, y = this;
int min = x.key;
while (x != null) {
if (x.key < min) {
y = x;
min = x.key;
}
x = x.sibling;
}
return y;
}
/* Function to find node with key value */
public BinomialHeapNode findANodeWithKey(int value)
{
BinomialHeapNode temp = this, node = null;
while (temp != null)
{
if (temp.key == value)
{
node = temp;
break;
}
if (temp.child == null)
temp = temp.sibling;
else
{
node = temp.child.findANodeWithKey(value);
if (node == null)
temp = temp.sibling;
else
break;
}
}
return node;
}
/* Function to get size */
public int getSize()
{
return (1 + ((child == null) ? 0 : child.getSize()) + ((sibling == null) ? 0 : sibling.getSize()));
}
}
二项堆:
class BinomialHeap
{
private BinomialHeapNode Nodes;
private int size;
/* Constructor */
public BinomialHeap()
{
Nodes = null;
size = 0;
}
/* Check if heap is empty */
public boolean isEmpty()
{
return Nodes == null;
}
/* Function to get size */
public int getSize()
{
return size;
}
/* clear heap */
public void makeEmpty()
{
Nodes = null;
size = 0;
}
/* Function to insert */
public void insert(int value)
{
if (value > 0)
{
BinomialHeapNode temp = new BinomialHeapNode(value);
if (Nodes == null)
{
Nodes = temp;
size = 1;
}
else
{
unionNodes(temp);
size++;
}
}
}
/* Function to unite two binomial heaps */
private void merge(BinomialHeapNode binHeap)
{
BinomialHeapNode temp1 = Nodes, temp2 = binHeap;
while ((temp1 != null) && (temp2 != null))
{
if (temp1.degree == temp2.degree)
{
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))
{
BinomialHeapNode tmp = temp2;
temp2 = temp2.sibling;
tmp.sibling = temp1.sibling;
temp1.sibling = tmp;
temp1 = tmp.sibling;
}
else
{
temp1 = temp1.sibling;
}
}
else
{
BinomialHeapNode tmp = temp1;
temp1 = temp2;
temp2 = temp2.sibling;
temp1.sibling = tmp;
if (tmp == Nodes)
{
Nodes = temp1;
}
else
{
}
}
}
}
if (temp1 == null)
{
temp1 = Nodes;
while (temp1.sibling != null)
{
temp1 = temp1.sibling;
}
temp1.sibling = temp2;
}
else
{
}
}
/* Function for union of nodes */
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)))
{
prevTemp = temp;
temp = nextTemp;
}
else
{
if (temp.key <= nextTemp.key)
{
temp.sibling = nextTemp.sibling;
nextTemp.parent = temp;
nextTemp.sibling = temp.child;
temp.child = nextTemp;
temp.degree++;
}
else
{
if (prevTemp == null)
{
Nodes = nextTemp;
}
else
{
prevTemp.sibling = nextTemp;
}
temp.parent = nextTemp;
temp.sibling = nextTemp.child;
nextTemp.child = temp;
nextTemp.degree++;
temp = nextTemp;
}
}
nextTemp = temp.sibling;
}
}
/* Function to return minimum key */
public int findMinimum()
{
return Nodes.findMinNode().key;
}
/* Function to delete a particular element */
public void delete(int value)
{
if ((Nodes != null) && (Nodes.findANodeWithKey(value) != null))
{
decreaseKeyValue(value, findMinimum() - 1);
extractMin();
}
}
/* Function to decrease key with a given value */
public void decreaseKeyValue(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;
temp.key = tempParent.key;
tempParent.key = z;
temp = tempParent;
tempParent = tempParent.parent;
}
}
/* Function to 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)
{
prevTemp = temp;
temp = temp.sibling;
}
if (prevTemp == null)
{
Nodes = temp.sibling;
}
else
{
prevTemp.sibling = temp.sibling;
}
temp = temp.child;
BinomialHeapNode fakeNode = temp;
while (temp != null)
{
temp.parent = null;
temp = temp.sibling;
}
if ((Nodes == null) && (fakeNode == null))
{
size = 0;
}
else
{
if ((Nodes == null) && (fakeNode != null))
{
Nodes = fakeNode.reverse(null);
size = Nodes.getSize();
}
else
{
if ((Nodes != null) && (fakeNode == null))
{
size = Nodes.getSize();
}
else
{
unionNodes(fakeNode.reverse(null));
size = Nodes.getSize();
}
}
}
return minNode.key;
}
/* Function to display heap */
public void displayHeap()
{
System.out.print("\nHeap : ");
displayHeap(Nodes);
System.out.println("\n");
}
private void displayHeap(BinomialHeapNode r)
{
if (r != null)
{
displayHeap(r.child);
System.out.print(r.key +" ");
displayHeap(r.sibling);
}
}
}
参考:
https://zh.wikipedia.org/wiki/%E4%BA%8C%E9%A1%B9%E5%A0%86
https://www.sanfoundry.com/java-program-implement-binomial-heap/
https://www.youtube.com/watch?v=7UQd9SYUoNk