Implementación de Binomial Heap | Establecer – 2 (eliminar() y decreseKey())

En una publicación anterior, es decir, el Conjunto 1, hemos discutido que implementa las siguientes funciones:

  1. insert(H, k): inserta una clave ‘k’ en el montón binomial ‘H’. Esta operación primero crea un montón binomial con una sola clave ‘k’, luego llama a la unión en H y al nuevo montón binomial.
  2. getMin(H): una forma sencilla de getMin() es recorrer la lista de raíces de los árboles binomiales y devolver la clave mínima. Esta implementación requiere tiempo O (Iniciar sesión). Puede optimizarse a O(1) manteniendo un puntero a la clave raíz mínima.
  3. extractMin(H): Esta operación también usa union(). Primero llamamos a getMin() para encontrar el árbol binomial clave mínimo, luego eliminamos el Node y creamos un nuevo montón binomial conectando todos los subárboles del Node mínimo eliminado. Finalmente, llamamos a union() en H y en el Binomial Heap recién creado. Esta operación requiere tiempo O (Iniciar sesión).

Ejemplos:

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

En esta publicación, se implementan las siguientes funciones.

  1. delete(H): Al igual que Binary Heap, la operación de eliminación primero reduce la clave a menos infinito, luego llama a extractMin().
  2. decrementarKey(H): decrementarKey() también es similar a Binary Heap. Comparamos la clave de disminución con su padre y si la clave del padre es más, intercambiamos claves y recurrimos para el padre. Nos detenemos cuando llegamos a un Node cuyo padre tiene una clave más pequeña o llegamos al Node raíz. La complejidad del tiempo de disminuirKey() es O (Iniciar sesión)

CPP

// C++ program for implementation of
// Binomial Heap and Operations on it
#include <bits/stdc++.h>
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 deleting 10, the heap is:\n";
 
    display(root);
 
    return 0;
}

Producción:

The heap is:
50 10 30 40 20 
After deleting 10, the heap is:
20 30 40 50 

Publicación traducida automáticamente

Artículo escrito por Sahil_Chhabra y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *