Open In App

Pairing Heap

Last Updated : 25 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Pairing Heap is like a simplified form Fibonacci Heap. It also maintains the property of min heap which is parent value is less than its child nodes value. It can be considered as a self-adjusting binomial heap.
Each node has a pointer towards the left child and left child points towards the next sibling of the child. 
Example of Pairing Heap is given below: 
 

Join or Merge in Pairing Heap 
To join the two heap, first, we compare the root node of the heap if the root node of the first heap is smaller than the root node of the second heap then root node of the second heap becomes a left child of the root node of the first heap otherwise vice-versa. The time complexity of this process is O(1).
Example of Merge is given Below: 
 

Merge

Insertion in Pairing Heap
To insert a new node in heap, create a new node and Merge it with existing heap as explained above. Therefore, the time complexity of this function is O(1). 
Example of Insertion is given below: 
 

insertion

Deletion in Pairing Heap
Deletion in Pairing Heap only happens at the root node. First delete links between root, left child and all the siblings of the left child. Then Merge tree subtrees that are obtained by detaching the left child and all siblings by the two pass method and delete the root node. Merge the detached subtrees from left to right in one pass and then merge the subtrees from right to left to form the new heap without violation of conditions of min-heap. This process takes O(log n) time where n is the number of nodes. 
Example of Deletion is given below: 
 

deletion

Below is the implementation of the above approach: 

CPP14




#include<bits/stdc++.h>
using namespace std;
 
// Heap structure
struct HeapNode {
 
    int key;
    HeapNode *leftChild;
    HeapNode *nextSibling;
 
    HeapNode():
        leftChild(NULL), nextSibling(NULL) {}
 
    // creates a new node
    HeapNode(int key_, HeapNode *leftChild_, HeapNode *nextSibling_):
        key(key_), leftChild(leftChild_), nextSibling(nextSibling_) {}
         
        // Adds a child and sibling to the node
    void addChild(HeapNode *node) {
        if(leftChild == NULL)
            leftChild = node;
        else {
            node->nextSibling = leftChild;
            leftChild = node;
        }
    }
};
 
// Returns true if root of the tree
// is null otherwise returns false
bool Empty(HeapNode *node) {
    return (node == NULL);
}
 
// Function to merge two heaps
HeapNode *Merge(HeapNode *A, HeapNode *B)
{
    // If any of the two-nodes is null
    // the return the not null node
    if(A == NULL) return B;
    if(B == NULL) return A;
     
    // To maintain the min heap condition compare   
    // the nodes and node with minimum value become 
    // parent of the other node
    if(A->key < B->key) {                 
        A->addChild(B);
        return A;        
    }
    else {
        B->addChild(A);
        return B;
    }
 
    return NULL; // Unreachable
}
 
// Returns the root value of the heap
int Top(HeapNode *node) {
    return node->key;
}
 
// Function to insert the new node in the heap
HeapNode *Insert(HeapNode *node, int key) {
    return Merge(node, new HeapNode(key, NULL, NULL));
}
 
// This method is used when we want to delete root node
HeapNode *TwoPassMerge(HeapNode *node) {
    if(node == NULL || node->nextSibling == NULL)
        return node;
    else {
        HeapNode *A, *B, *newNode;
        A = node;
        B = node->nextSibling;
        newNode = node->nextSibling->nextSibling;
 
        A->nextSibling = NULL;
        B->nextSibling = NULL;
 
        return Merge(Merge(A, B), TwoPassMerge(newNode));
    }
 
    return NULL; // Unreachable
}
 
// Function to delete the root node in heap
HeapNode *Delete(HeapNode *node) {
    return TwoPassMerge(node->leftChild);
}
 
struct PairingHeap {
    HeapNode *root;
 
    PairingHeap():
        root(NULL) {}
 
    bool Empty(void) {
        return ::Empty(root);
    }
 
    int Top(void) {
        return ::Top(root);
    }
 
    void Insert(int key) {
        root = ::Insert(root, key);
    }
 
    void Delete(void) {
        root = ::Delete(root);
    }
 
    void Join(PairingHeap other) {
        root = ::Merge(root, other.root);
    }
     
};
 
// Driver Code
int main(void) {
 
    PairingHeap heap1, heap2;
    heap2.Insert(5);
    heap2.Insert(2);
 
    heap2.Insert(6);
    heap1.Insert(1);
    heap1.Insert(3);
    heap1.Insert(4);
     
    heap1.Join(heap2);
     
    cout << heap1.Top() << endl;
    heap1.Delete();
 
    cout << heap1.Top() << endl;
    cout<< (heap1.Empty()?"True":"False");
     
    return 0;
}


Java




import java.util.*;
 
// Heap structure
class HeapNode {
 
    int key;
    HeapNode leftChild;
    HeapNode nextSibling;
 
    public HeapNode() {
        leftChild = null;
        nextSibling = null;
    }
 
    // creates a new node
    public HeapNode(int key_, HeapNode leftChild_, HeapNode nextSibling_) {
        key = key_;
        leftChild = leftChild_;
        nextSibling = nextSibling_;
    }
 
    // Adds a child and sibling to the node
    public void addChild(HeapNode node) {
        if (leftChild == null)
            leftChild = node;
        else {
            node.nextSibling = leftChild;
            leftChild = node;
        }
    }
}
 
// Pairing Heap implementation
class PairingHeap {
    HeapNode root;
 
    public PairingHeap() {
        root = null;
    }
 
    public boolean isEmpty() {
        return root == null;
    }
 
    public int top() {
        return root.key;
    }
 
    public void insert(int key) {
        root = insert(root, key);
    }
 
    public void delete() {
        root = delete(root);
    }
 
    public void join(PairingHeap other) {
        root = merge(root, other.root);
    }
 
    // Helper functions
    private HeapNode insert(HeapNode node, int key) {
        return merge(node, new HeapNode(key, null, null));
    }
 
    private HeapNode delete(HeapNode node) {
        return twoPassMerge(node.leftChild);
    }
 
    private HeapNode merge(HeapNode a, HeapNode b) {
        // If any of the two nodes is null,
        // return the not null node
        if (a == null)
            return b;
        if (b == null)
            return a;
 
        // To maintain the min heap condition compare
        // the nodes and node with minimum value become
        // parent of the other node
        if (a.key < b.key) {
            a.addChild(b);
            return a;
        } else {
            b.addChild(a);
            return b;
        }
    }
 
    private HeapNode twoPassMerge(HeapNode node) {
        if (node == null || node.nextSibling == null)
            return node;
        else {
            HeapNode a, b, newNode;
            a = node;
            b = node.nextSibling;
            newNode = node.nextSibling.nextSibling;
 
            a.nextSibling = null;
            b.nextSibling = null;
 
            return merge(merge(a, b), twoPassMerge(newNode));
        }
    }
 
}
 
// Driver code
public class Main {
    public static void main(String[] args) {
 
        PairingHeap heap1 = new PairingHeap();
        PairingHeap heap2 = new PairingHeap();
 
        heap2.insert(5);
        heap2.insert(2);
        heap2.insert(6);
 
        heap1.insert(1);
        heap1.insert(3);
        heap1.insert(4);
 
        heap1.join(heap2);
 
        System.out.println(heap1.top());
        heap1.delete();
 
        System.out.println(heap1.top());
        System.out.println(heap1.isEmpty() ? "True" : "False");
    }
}
 
// Contributed by adityasharmadev01


Python3




# Heap structure
class HeapNode:
 
    # creates a new node
    def __init__(self, key_=None, leftChild_=None, nextSibling_=None):
        self.key = key_
        self.leftChild = leftChild_
        self.nextSibling = nextSibling_
 
    # Adds a child and sibling to the node
    def addChild(self, node):
        if(self.leftChild == None):
            self.leftChild = node
        else:
            node.nextSibling = self.leftChild
            self.leftChild = node
 
# Returns true if root of the tree
# is None otherwise returns false
 
 
def Empty(node):
    return (node == None)
 
# Function to merge two heaps
 
 
def Merge(A, B):
 
    # If any of the two-nodes is None
    # the return the not None node
    if(A == None):
        return B
    if(B == None):
        return A
 
    # To maintain the min heap condition compare
    # the nodes and node with minimum value become
    # parent of the other node
    if(A.key < B.key):
        A.addChild(B)
        return A
    B.addChild(A)
    return B
 
# Returns the root value of the heap
 
 
def Top(node):
    return node.key
 
 
# Function to insert the new node in the heap
def Insert(node, key):
    return Merge(node, HeapNode(key,))
 
 
# This method is used when we want to delete root node
def TwoPassMerge(node):
    if(node == None or node.nextSibling == None):
        return node
    A = node
    B = node.nextSibling
    newNode = node.nextSibling.nextSibling
 
    A.nextSibling = None
    B.nextSibling = None
 
    return Merge(Merge(A, B), TwoPassMerge(newNode))
 
 
# Function to delete the root node in heap
def Delete(node):
    return TwoPassMerge(node.leftChild)
 
 
class PairingHeap:
    def __init__(self):
        self.root = None
 
    def Empty(self):
        return Empty(self.root)
 
    def Top(self):
        return Top(self.root)
 
    def Insert(self, key):
        self.root = Insert(self.root, key)
 
    def Delete(self):
        self.root = Delete(self.root)
 
    def Join(self, other):
        self.root = Merge(self.root, other.root)
 
 
# Driver Code
if __name__ == '__main__':
 
    heap1, heap2 = PairingHeap(), PairingHeap()
    heap2.Insert(5)
    heap2.Insert(2)
 
    heap2.Insert(6)
    heap1.Insert(1)
    heap1.Insert(3)
    heap1.Insert(4)
 
    heap1.Join(heap2)
 
    print(heap1.Top())
    heap1.Delete()
 
    print(heap1.Top())
    print(heap1.Empty())
# This code is contributed by Amartya Ghosh


C#




// C# code for the above approach
 
using System;
 
namespace GFG
{
    // Heap structure
    class HeapNode
    {
        public int Key { get; set; }
        public HeapNode LeftChild { get; set; }
        public HeapNode NextSibling { get; set; }
 
        public HeapNode()
        {
            LeftChild = null;
            NextSibling = null;
        }
     
    // Creates a new node
        public HeapNode(int key, HeapNode leftChild, HeapNode nextSibling)
        {
            Key = key;
            LeftChild = leftChild;
            NextSibling = nextSibling;
        }
    // Adds a child and sibling to the node
        public void AddChild(HeapNode node)
        {
            if (LeftChild == null)
                LeftChild = node;
            else
            {
                node.NextSibling = LeftChild;
                LeftChild = node;
            }
        }
    }
 
    class PairingHeap
    {
        private HeapNode root;
 
        public PairingHeap()
        {
            root = null;
        }
    // Returns true if root of the tree
    // is null otherwise returns false
        public bool IsEmpty()
        {
            return root == null;
        }
     
    // Returns the root value of the heap
        public int Top()
        {
            return root.Key;
        }
    // Function to insert the new node in the heap
        public void Insert(int key)
        {
            root = Merge(root, new HeapNode(key, null, null));
        }
         
    // Function to delete the root node in heap
        public void Delete()
        {
            root = TwoPassMerge(root.LeftChild);
        }
 
        public void Join(PairingHeap other)
        {
            root = Merge(root, other.root);
        }
         
        // Function to merge two heaps
        private HeapNode Merge(HeapNode A, HeapNode B)
        {
        // If any of the two-nodes is null
        // the return the not null node
         
            if (A == null) return B;
            if (B == null) return A;
             
        // To maintain the min heap condition compare  
        // the nodes and node with minimum value become
        // parent of the other node
            if (A.Key < B.Key)
            {
                A.AddChild(B);
                return A;
            }
            else
            {
                B.AddChild(A);
                return B;
            }
        }
 
    // This method is used when we want to delete root node
        private HeapNode TwoPassMerge(HeapNode node)
        {
            if (node == null || node.NextSibling == null)
                return node;
 
            HeapNode A, B, newNode;
            A = node;
            B = node.NextSibling;
            newNode = node.NextSibling.NextSibling;
 
            A.NextSibling = null;
            B.NextSibling = null;
 
            return Merge(Merge(A, B), TwoPassMerge(newNode));
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            PairingHeap heap1 = new PairingHeap();
            PairingHeap heap2 = new PairingHeap();
            heap2.Insert(5);
            heap2.Insert(2);
            heap2.Insert(6);
            heap1.Insert(1);
            heap1.Insert(3);
            heap1.Insert(4);
 
            heap1.Join(heap2);
 
            Console.WriteLine(heap1.Top());
            heap1.Delete();
            Console.WriteLine(heap1.Top());
            Console.WriteLine(heap1.IsEmpty() ? "True" : "False");
        }
    }
}
 
// This code is contributed by Abhinav Mahajan (abhinav_m22).


Javascript




// Heap structure
class HeapNode {
  constructor(key, leftChild, nextSibling) {
    this.key = key;
    this.leftChild = leftChild || null;
    this.nextSibling = nextSibling || null;
  }
 
  // Adds a child and sibling to the node
  addChild(node) {
    if (this.leftChild === null) {
      this.leftChild = node;
    } else {
      node.nextSibling = this.leftChild;
      this.leftChild = node;
    }
  }
}
 
// Returns true if root of the tree
// is null otherwise returns false
function Empty(node) {
  return node === null;
}
 
// Function to merge two heaps
function Merge(A, B) {
  // If any of the two-nodes is null
  // the return the not null node
  if (A === null) {
    return B;
  }
  if (B === null) {
    return A;
  }
 
  // To maintain the min heap condition compare
  // the nodes and node with minimum value become
  // parent of the other node
  if (A.key < B.key) {
    A.addChild(B);
    return A;
  } else {
    B.addChild(A);
    return B;
  }
}
 
// Returns the root value of the heap
function Top(node) {
  return node.key;
}
 
// Function to insert the new node in the heap
function Insert(node, key) {
  return Merge(node, new HeapNode(key, null, null));
}
 
// This method is used when we want to delete root node
function TwoPassMerge(node) {
  if (node === null || node.nextSibling === null) {
    return node;
  } else {
    let A = node;
    let B = node.nextSibling;
    let newNode = node.nextSibling.nextSibling;
 
    A.nextSibling = null;
    B.nextSibling = null;
 
    return Merge(Merge(A, B), TwoPassMerge(newNode));
  }
}
 
// Function to delete the root node in heap
function Delete(node) {
  return TwoPassMerge(node.leftChild);
}
 
class PairingHeap {
  constructor() {
    this.root = null;
  }
 
  empty() {
    return Empty(this.root);
  }
 
  top() {
    return Top(this.root);
  }
 
  insert(key) {
    this.root = Insert(this.root, key);
  }
 
  delete() {
    this.root = Delete(this.root);
  }
 
  join(other) {
    this.root = Merge(this.root, other.root);
  }
}
 
// Driver Code
const heap1 = new PairingHeap();
const heap2 = new PairingHeap();
heap2.insert(5);
heap2.insert(2);
heap2.insert(6);
heap1.insert(1);
heap1.insert(3);
heap1.insert(4);
heap1.join(heap2);
console.log(heap1.top());
heap1.delete();
console.log(heap1.top());
console.log(heap1.empty() ? "True" : "False");


Output

1
2
False

Time Complexity: 
Insertion: O(1)
Merge: O(1)
Deletion: O(logN) 
Auxiliary Space: O(1).  



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads