package com.thealgorithms.datastructures.heaps;
import java.util.ArrayList;
/*
* This is a leftist heap that follows the same operations as a
* binary min heap, but may be unbalanced at times and follows a
* leftist property, in which the left side is more heavy on the
* right based on the null-path length (npl) values.
*
* Source: https://iq.opengenus.org/leftist-heap/
*
*/
public class LeftistHeap {
private class Node {
private int element, npl;
private Node left, right;
// Node constructor setting the data element and left/right pointers to null
private Node(int element) {
this.element = element;
left = right = null;
npl = 0;
}
}
private Node root;
// Constructor
public LeftistHeap() {
root = null;
}
// Checks if heap is empty
public boolean isEmpty() {
return root == null;
}
// Resets structure to initial state
public void clear() {
// We will put head is null
root = null;
}
// Merge function that merges the contents of another leftist heap with the
// current one
public void merge(LeftistHeap h1) {
// If the present function is rhs then we ignore the merge
root = merge(root, h1.root);
h1.root = null;
}
// Function merge with two Nodes a and b
public Node merge(Node a, Node b) {
if (a == null) return b;
if (b == null) return a;
// Violates leftist property, so must do a swap
if (a.element > b.element) {
Node temp = a;
a = b;
b = temp;
}
// Now we call the function merge to merge a and b
a.right = merge(a.right, b);
// Violates leftist property so must swap here
if (a.left == null) {
a.left = a.right;
a.right = null;
} else {
if (a.left.npl < a.right.npl) {
Node temp = a.left;
a.left = a.right;
a.right = temp;
}
a.npl = a.right.npl + 1;
}
return a;
}
// Function insert. Uses the merge function to add the data
public void insert(int a) {
root = merge(new Node(a), root);
}
// Returns and removes the minimum element in the heap
public int extract_min() {
// If is empty return -1
if (isEmpty()) return -1;
int min = root.element;
root = merge(root.left, root.right);
return min;
}
// Function returning a list of an in order traversal of the data structure
public ArrayList<Integer> in_order() {
ArrayList<Integer> lst = new ArrayList<>();
in_order_aux(root, lst);
return new ArrayList<>(lst);
}
// Auxiliary function for in_order
private void in_order_aux(Node n, ArrayList<Integer> lst) {
if (n == null) return;
in_order_aux(n.left, lst);
lst.add(n.element);
in_order_aux(n.right, lst);
}
}