Open In App

Skew Heap

Last Updated : 20 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

A skew heap (or self – adjusting heap) is a heap data structure implemented as a binary tree. Skew heaps are advantageous because of their ability to merge more quickly than binary heaps. In contrast with binary heaps, there are no structural constraints, so there is no guarantee that the height of the tree is logarithmic. Only two conditions must be satisfied : 

  1. The general heap order must be there (root is minimum and same is recursively true for subtrees), but balanced property (all levels must be full except the last) is not required.
  2. Main operation in Skew Heaps is Merge. We can implement other operations like insert, extractMin(), etc using Merge only.

Example : 
1. Consider the skew heap 1 to be  

2. The second heap to be considered 

4. And we obtain the final merged tree as 
 

Recursive Merge Process : 
merge(h1, h2) 

  1. Let h1 and h2 be the two min skew heaps to be merged. Let h1’s root be smaller than h2’s root (If not smaller, we can swap to get the same).
  2. We swap h1->left and h1->right.
  3. h1->left = merge(h2, h1->left)

Examples : 

Let h1 be
        10
     /    \
   20      30
  /        /
40        50

Let h2 be
       15
     /    \
   25      35
  /  \
45    55

After swapping h1->left and h1->right, we get
        10
     /    \
   30      20
  /        /
50        40

Now we recursively Merge
   30
   /     AND   
  50

       15
     /    \
   25      35
  /  \
45    55
After recursive merge, we get (Please do it 
using pen and paper).
        15
     /     \
   30        25
  /  \     /    \
35    50  45    55

We make this merged tree as left of original
h1 and we get following result.
             10
         /         \
       15           20
    /      \       /   
   30       25    40   
 /   \    /    \
35   40  45    55

For visualization : https://www.cs.usfca.edu/~galles/JavascriptVisual/LeftistHeap.html 

Implementation:

CPP




// CPP program to implement Skew Heap
// operations.
#include <bits/stdc++.h>
using namespace std;
 
struct SkewHeap
{
    int key;
    SkewHeap* right;
    SkewHeap* left;
 
    // constructor to make a new
    // node of heap
    SkewHeap()
    {
        key = 0;
        right = NULL;
        left = NULL;
    }
 
    // the special merge function that's
    // used in most of the other operations
    // also
    SkewHeap* merge(SkewHeap* h1, SkewHeap* h2)
    {
        // If one of the heaps is empty
        if (h1 == NULL)
            return h2;
        if (h2 == NULL)
            return h1;
 
        // Make sure that h1 has smaller
        // key.
        if (h1->key > h2->key)
           swap(h1, h2);
 
        // Swap h1->left and h1->right
        swap(h1->left, h1->right);
 
        // Merge h2 and h1->left and make
        // merged tree as left of h1.
        h1->left = merge(h2, h1->left);
 
        return h1;
    }
 
    // function to construct heap using
    // values in the array
    SkewHeap* construct(SkewHeap* root,
                     int heap[], int n)
    {
        SkewHeap* temp;
        for (int i = 0; i < n; i++) {
            temp = new SkewHeap;
            temp->key = heap[i];
            root = merge(root, temp);
        }
        return root;
    }
 
    // function to print the Skew Heap,
    // as it is in form of a tree so we use
    // tree traversal algorithms
    void inorder(SkewHeap* root)
    {
        if (root == NULL)
            return;
        else {
            inorder(root->left);
            cout << root->key << "  ";
            inorder(root->right);
        }
        return;
    }
};
 
// Driver Code
int main()
{
    // Construct two heaps
    SkewHeap heap, *temp1 = NULL,
                   *temp2 = NULL;
    /*
            5
           / \
          /   \
         10   12    */
    int heap1[] = { 12, 5, 10 };
    /*
            3
           / \
          /   \
         7     8
        /
       /
      14    */
    int heap2[] = { 3, 7, 8, 14 };
    int n1 = sizeof(heap1) / sizeof(heap1[0]);
    int n2 = sizeof(heap2) / sizeof(heap2[0]);
    temp1 = heap.construct(temp1, heap1, n1);
    temp2 = heap.construct(temp2, heap2, n2);
 
    // Merge two heaps
    temp1 = heap.merge(temp1, temp2);
    /*
            3
           / \
          /   \
         5     7
        / \   /
       8  10 14
      /
     12    */
    cout << "Merged Heap is: " << endl;
    heap.inorder(temp1);
}


Java




// Java program to implement Skew Heap operations.
import java.util.*;
 
class SkewHeap {
    int key;
    SkewHeap right;
    SkewHeap left;
 
    // constructor to make a new
    // node of heap
    SkewHeap()
    {
        key = 0;
        right = null;
        left = null;
    }
 
    // the special merge function that's
    // used in most of the other operations
    // also
    SkewHeap merge(SkewHeap h1, SkewHeap h2)
    {
        // If one of the heaps is empty
        if (h1 == null)
            return h2;
        if (h2 == null)
            return h1;
 
        // Make sure that h1 has smaller
        // key.
        if (h1.key > h2.key) {
            SkewHeap temp = h1;
            h1 = h2;
            h2 = temp;
        }
 
        // Swap h1.left and h1.right
        SkewHeap temp = h1.left;
        h1.left = h1.right;
        h1.right = temp;
 
        // Merge h2 and h1.left and make
        // merged tree as left of h1.
        h1.left = merge(h2, h1.left);
 
        return h1;
    }
 
    // function to construct heap using
    // values in the array
    SkewHeap construct(SkewHeap root, int[] heap, int n)
    {
        SkewHeap temp;
        for (int i = 0; i < n; i++) {
            temp = new SkewHeap();
            temp.key = heap[i];
            root = merge(root, temp);
        }
        return root;
    }
 
    // function to print the Skew Heap,
    // as it is in form of a tree so we use
    // tree traversal algorithms
    void inorder(SkewHeap root)
    {
        if (root == null)
            return;
        else {
            inorder(root.left);
            System.out.print(root.key + "  ");
            inorder(root.right);
        }
        return;
    }
}
 
// Driver Code
public class Main {
    public static void main(String[] args)
    {
        // Construct two heaps
        SkewHeap heap = new SkewHeap(), temp1 = null,
                 temp2 = null;
        /*
        5
        /
        /
        10 12 /
        
        /
        3
        /
        /
        7 8
        /
        /
        14 */
       int[] heap1 = { 12, 5, 10 };
        int[] heap2 = { 3, 7, 8, 14 };
        int n1 = heap1.length;
        int n2 = heap2.length;
        temp1 = heap.construct(temp1, heap1, n1);
        temp2 = heap.construct(temp2, heap2, n2);
 
        // Merge two heaps
        temp1 = heap.merge(temp1, temp2);
        /*
            3
           / \
          /   \
         5     7
        / \   /
       8  10 14
      /
     12    */
        System.out.println("Merged Heap is: ");
        heap.inorder(temp1);
    }
}


Python3




# Python code implementation
 
class SkewHeap:
    def __init__(self):
        self.key = 0
        self.right = None
        self.left = None
 
    # the special merge function that's used
    # in most of the other operations also
    def merge(self, h1, h2):
        # If one of the heaps is empty
        if h1 is None:
            return h2
        if h2 is None:
            return h1
 
        # Make sure that h1 has smaller key.
        if h1.key > h2.key:
            h1, h2 = h2, h1
 
        # Swap h1.left and h1.right
        h1.left, h1.right = h1.right, h1.left
 
        # Merge h2 and h1.left and make
        # merged tree as left of h1.
        h1.left = self.merge(h2, h1.left)
 
        return h1
 
    # function to construct heap using values in the array
    def construct(self, root, heap, n):
        for i in range(n):
            temp = SkewHeap()
            temp.key = heap[i]
            root = self.merge(root, temp)
        return root
 
    # function to print the Skew Heap, as it is
    # in form of a tree so we use
    # tree traversal algorithms
    def inorder(self, root):
        if root is None:
            return
        else:
            self.inorder(root.left)
            print(root.key, end="  ")
            self.inorder(root.right)
 
# Driver Code
if __name__ == "__main__":
    # Construct two heaps
    heap, temp1, temp2 = SkewHeap(), None, None
    heap1 = [12, 5, 10]
    heap2 = [3, 7, 8, 14]
    n1 = len(heap1)
    n2 = len(heap2)
    temp1 = heap.construct(temp1, heap1, n1)
    temp2 = heap.construct(temp2, heap2, n2)
 
    # Merge two heaps
    temp1 = heap.merge(temp1, temp2)
 
    print("The heap obtained after merging is:")
    heap.inorder(temp1)
 
# This code is contributed by karthik.


C#




using System;
 
class SkewHeap {
    int key;
    SkewHeap right;
    SkewHeap left;
 
    // constructor to make a new
    // node of heap
    public SkewHeap()
    {
        key = 0;
        right = null;
        left = null;
    }
 
    // the special merge function that's
    // used in most of the other operations
    // also
    public SkewHeap merge(SkewHeap h1, SkewHeap h2)
    {
        // If one of the heaps is empty
        if (h1 == null)
            return h2;
        if (h2 == null)
            return h1;
 
        // Make sure that h1 has smaller
        // key.
        if (h1.key > h2.key) {
            SkewHeap temp = h1;
            h1 = h2;
            h2 = temp;
        }
 
        // Swap h1.left and h1.right
        SkewHeap temp2 = h1.left;
        h1.left = h1.right;
        h1.right = temp2;
 
        // Merge h2 and h1.left and make
        // merged tree as left of h1.
        h1.left = merge(h2, h1.left);
 
        return h1;
    }
 
    // function to construct heap using
    // values in the array
    public SkewHeap construct(SkewHeap root, int[] heap,
                              int n)
    {
        SkewHeap temp;
        for (int i = 0; i < n; i++) {
            temp = new SkewHeap();
            temp.key = heap[i];
            root = merge(root, temp);
        }
        return root;
    }
 
    // function to print the Skew Heap,
    // as it is in form of a tree so we use
    // tree traversal algorithms
    public void inorder(SkewHeap root)
    {
        if (root == null)
            return;
        else {
            inorder(root.left);
            Console.Write(root.key + "  ");
            inorder(root.right);
        }
        return;
    }
}
 
// Driver Code
class Program {
    static void Main(string[] args)
    {
        // Construct two heaps
        SkewHeap heap = new SkewHeap(), temp1 = null,
                 temp2 = null;
        /*
        5
        /
        /
        10 12 /
 
 
            /
            3
            /
            /
            7 8
            /
            /
            14 */
        int[] heap1 = { 12, 5, 10 };
        int[] heap2 = { 3, 7, 8, 14 };
        int n1 = heap1.Length;
        int n2 = heap2.Length;
        temp1 = heap.construct(temp1, heap1, n1);
        temp2 = heap.construct(temp2, heap2, n2);
 
        // Merge two heaps
        temp1 = heap.merge(temp1, temp2);
        /*
            3
           / \
          /   \
         5     7
        / \   /
       8  10 14
      /
     12    */
        Console.WriteLine("Merged Heap is: ");
        heap.inorder(temp1);
    }
}


Javascript




// JavaScript code implementation
class SkewHeap {
  constructor() {
    this.key = 0;
    this.right = null;
    this.left = null;
  }
 
  // the special merge function that's
  // used in most of the other operations
  // also
  merge(h1, h2) {
    // If one of the heaps is empty
    if (h1 == null) return h2;
    if (h2 == null) return h1;
 
    // Make sure that h1 has smaller key.
    if (h1.key > h2.key) {
      [h1, h2] = [h2, h1];
    }
 
    // Swap h1.left and h1.right
    [h1.left, h1.right] = [h1.right, h1.left];
 
    // Merge h2 and h1.left and make merged tree as left of h1.
    h1.left = this.merge(h2, h1.left);
 
    return h1;
  }
 
  // function to construct heap using values in the array
  construct(root, heap, n) {
    let temp;
    for (let i = 0; i < n; i++) {
      temp = new SkewHeap();
      temp.key = heap[i];
      root = this.merge(root, temp);
    }
    return root;
  }
 
  // function to print the Skew Heap,
  // as it is in form of a tree so we use
  // tree traversal algorithms
  inorder(root) {
    if (root == null) return;
    else {
      this.inorder(root.left);
      console.log(root.key + "  ");
      this.inorder(root.right);
    }
    return;
  }
}
 
// Driver Code
// Construct two heaps
let heap = new SkewHeap(),
  temp1 = null,
  temp2 = null;
 
let heap1 = [12, 5, 10];
let heap2 = [3, 7, 8, 14];
let n1 = heap1.length;
let n2 = heap2.length;
temp1 = heap.construct(temp1, heap1, n1);
temp2 = heap.construct(temp2, heap2, n2);
 
// Merge two heaps
temp1 = heap.merge(temp1, temp2);
 
console.log("The heap obtained after merging is: <br>");
heap.inorder(temp1);
 
// This code is contributed by sankar.


Output: 

The heap obtained after merging is: 
12  8  5  10  3  14  7

 

Time Complexity: O(NlogN)

Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads