在上一篇文章Set 1中,我们讨论了实现以下功能的方法:
- insert(H,k):将键“ k”插入二项式堆“ H”。此操作首先创建具有单键“ k”的二项式堆,然后在H和新的二项式堆上调用并集。
- getMin(H):一种简单的getMin()方法是遍历二叉树的根列表并返回最小键。此实现需要O(Logn)时间。可以通过维护指向最小密钥根的指针来将其优化为O(1)。
- extractMin(H):此操作还使用union()。我们首先调用getMin()来找到最小键二项式树,然后删除该节点,并通过连接删除的最小节点的所有子树来创建一个新的二项式堆。最后,我们在H和新创建的二项式堆上调用union()。此操作需要O(Logn)时间。
例子:
12------------10--------------------20
/ \ / | \
15 50 70 50 40
| / | |
30 80 85 65
|
100
A Binomial Heap with 13 nodes. It is a collection of 3
Binomial Trees of orders 0, 2 and 3 from left to right.
10--------------------20
/ \ / | \
15 50 70 50 40
| / | |
30 80 85 65
|
100
在这篇文章中,实现了以下功能。
- delete(H):与Binary Heap一样,delete操作首先将键减小为负无穷大,然后调用extractMin()。
- reductionKey(H): reductionKey()也类似于Binary Heap。我们将减少键与它的父键进行比较,如果父键的键更多,则交换键并为父键递归。当到达父级键较小的节点或击中根节点时,我们将停止。 reductionKey()的时间复杂度为O(Logn)
// C++ program for implementation of
// Binomial Heap and Operations on it
#include
using namespace std;
// Structure of Node
struct Node
{
int val, degree;
Node *parent, *child, *sibling;
};
// Making root global to avoid one extra
// parameter in all functions.
Node *root = NULL;
// link two heaps by making h1 a child
// of h2.
int binomialLink(Node *h1, Node *h2)
{
h1->parent = h2;
h1->sibling = h2->child;
h2->child = h1;
h2->degree = h2->degree + 1;
}
// create a Node
Node *createNode(int n)
{
Node *new_node = new Node;
new_node->val = n;
new_node->parent = NULL;
new_node->sibling = NULL;
new_node->child = NULL;
new_node->degree = 0;
return new_node;
}
// This function merge two Binomial Trees
Node *mergeBHeaps(Node *h1, Node *h2)
{
if (h1 == NULL)
return h2;
if (h2 == NULL)
return h1;
// define a Node
Node *res = NULL;
// check degree of both Node i.e.
// which is greater or smaller
if (h1->degree <= h2->degree)
res = h1;
else if (h1->degree > h2->degree)
res = h2;
// traverse till if any of heap gets empty
while (h1 != NULL && h2 != NULL)
{
// if degree of h1 is smaller, increment h1
if (h1->degree < h2->degree)
h1 = h1->sibling;
// Link h1 with h2 in case of equal degree
else if (h1->degree == h2->degree)
{
Node *sib = h1->sibling;
h1->sibling = h2;
h1 = sib;
}
// if h2 is greater
else
{
Node *sib = h2->sibling;
h2->sibling = h1;
h2 = sib;
}
}
return res;
}
// This function perform union operation on two
// binomial heap i.e. h1 & h2
Node *unionBHeaps(Node *h1, Node *h2)
{
if (h1 == NULL && h2 == NULL)
return NULL;
Node *res = mergeBHeaps(h1, h2);
// Traverse the merged list and set
// values according to the degree of
// Nodes
Node *prev = NULL, *curr = res,
*next = curr->sibling;
while (next != NULL)
{
if ((curr->degree != next->degree) ||
((next->sibling != NULL) &&
(next->sibling)->degree ==
curr->degree))
{
prev = curr;
curr = next;
}
else
{
if (curr->val <= next->val)
{
curr->sibling = next->sibling;
binomialLink(next, curr);
}
else
{
if (prev == NULL)
res = next;
else
prev->sibling = next;
binomialLink(curr, next);
curr = next;
}
}
next = curr->sibling;
}
return res;
}
// Function to insert a Node
void binomialHeapInsert(int x)
{
// Create a new node and do union of
// this node with root
root = unionBHeaps(root, createNode(x));
}
// Function to display the Nodes
void display(Node *h)
{
while (h)
{
cout << h->val << " ";
display(h->child);
h = h->sibling;
}
}
// Function to reverse a list
// using recursion.
int revertList(Node *h)
{
if (h->sibling != NULL)
{
revertList(h->sibling);
(h->sibling)->sibling = h;
}
else
root = h;
}
// Function to extract minimum value
Node *extractMinBHeap(Node *h)
{
if (h == NULL)
return NULL;
Node *min_node_prev = NULL;
Node *min_node = h;
// Find minimum value
int min = h->val;
Node *curr = h;
while (curr->sibling != NULL)
{
if ((curr->sibling)->val < min)
{
min = (curr->sibling)->val;
min_node_prev = curr;
min_node = curr->sibling;
}
curr = curr->sibling;
}
// If there is a single Node
if (min_node_prev == NULL &&
min_node->sibling == NULL)
h = NULL;
else if (min_node_prev == NULL)
h = min_node->sibling;
// Remove min node from list
else
min_node_prev->sibling = min_node->sibling;
// Set root (which is global) as children
// list of min node
if (min_node->child != NULL)
{
revertList(min_node->child);
(min_node->child)->sibling = NULL;
}
// Do union of root h and children
return unionBHeaps(h, root);
}
// Function to search for an element
Node *findNode(Node *h, int val)
{
if (h == NULL)
return NULL;
// check if key is equal to the root's data
if (h->val == val)
return h;
// Recur for child
Node *res = findNode(h->child, val);
if (res != NULL)
return res;
return findNode(h->sibling, val);
}
// Function to decrease the value of old_val
// to new_val
void decreaseKeyBHeap(Node *H, int old_val,
int new_val)
{
// First check element present or not
Node *node = findNode(H, old_val);
// return if Node is not present
if (node == NULL)
return;
// Reduce the value to the minimum
node->val = new_val;
Node *parent = node->parent;
// Update the heap according to reduced value
while (parent != NULL && node->val < parent->val)
{
swap(node->val, parent->val);
node = parent;
parent = parent->parent;
}
}
// Function to delete an element
Node *binomialHeapDelete(Node *h, int val)
{
// Check if heap is empty or not
if (h == NULL)
return NULL;
// Reduce the value of element to minimum
decreaseKeyBHeap(h, val, INT_MIN);
// Delete the minimum element from heap
return extractMinBHeap(h);
}
// Driver code
int main()
{
// Note that root is global
binomialHeapInsert(10);
binomialHeapInsert(20);
binomialHeapInsert(30);
binomialHeapInsert(40);
binomialHeapInsert(50);
cout << "The heap is:\n";
display(root);
// Delete a particular element from heap
root = binomialHeapDelete(root, 10);
cout << "\nAfter deleing 10, the heap is:\n";
display(root);
return 0;
}
输出:
The heap is:
50 10 30 40 20
After deleing 10, the heap is:
20 30 40 50