Data Structure-Heap

Keywords: Java less

Binary Heap

The binary heap is a binary tree, not necessarily a full binary tree, but must be a complete binary tree. A complete binary tree is a part that allows missing nodes, but the part that missing nodes must be on the lower right.

Any node in the heap must have a value greater than or equal to its child node.This feature also shows that the element of the root node is the largest element.Such a heap is called the maximum heap, whereas if any node is less than or equal to its child node, it is the minimum heap.Note here that not the closer to the root node, the larger the value.

Since the maximum heap is a complete binary tree, the maximum heap can be implemented as a bottom-level array.As shown, numbers 1-10 represent the index of an array, or 0-9 is OK.

If represented by a 1-10 index, such as 41, which has an index of 2, his left child index is 4 (i x 2) and his right child node is 5 (i x 2 + 1).
Conversely, knowing the left or right child, dividing the parent node directly by 2 is enough, and 4/2, 5/2 strong turns to int and then both are 2.
If these elements are represented by a 0-9 index, the parent node index is known to be 1, the left child node is 4 (i x 2 + 1), the right child node is 5 (i x 2 + 2), and the left or right child index is known to be 3 and 4, and the parent node index is 1 (i - 1) / 2.

Knowing these features, start implementing a maximum heap with code

//Using arrays as underlying data structures
public MyArray<E> myArray;
 
public MaxHeap(int capacity){
    myArray = new MyArray<>(capacity);
}

public MaxHeap(){
    myArray = new MyArray<>();
}

//Index of parent node (i-1)/2
public int parent(int index){
    if(index == 0)
        throw new IllegalArgumentException("index: 0,doesn't hava parent.");
    return (index - 1) / 2;
}

//Left Child Node i\*2+1
public int leftChild(int index){
    return index \* 2 + 1;
}

//Right Child Node i\*2+2
public int rightChild(int index){
    return index \* 2 + 2;
}

Add a Node

When adding nodes, there are two points to satisfy the nature of the maximum heap. The first is to add to the end of the array to satisfy the characteristics of a full binary tree.The second is to satisfy the feature that each node is larger than its child node. After 52 is added to the end, keep looking up for the parent node. After comparing the size of the parent node with the parent node, swap with the parent node element to find its own suitable location. We call this operation ShiftUp (floating up)

public void add(E e){
    myArray.addLast(e);
    shiftUp(myArray.getSize() - 1);
}

private void shiftUp(int index){
    //Compare the current index value with the parent node value and move up less than the parent node
    while(index > 0 && myArray.getByIndex(index).compareTo(myArray.getByIndex(parent(index))) > 0)
    {
        //Exchange between two indexes
        myArray.swap(index,parent(index));
        
        //Remark index position for next interchange logic
        index = parent(index);
    }
}

Take out the root element


If you want to take out the root element 62, the index 0 will be empty, and the binary tree will need to be reorganized to satisfy the structure of the largest heap.By placing the last element at the root element, and then relying on that element, we continually go down to determine if we are larger than both child nodes and do not need to move if we are older.If they are smaller than the children node, move down because there are two children who also need to compare who is older and who is older to exchange with.This process is called shift down.

//Take out the largest element
public E extractMax()
{
    E max = findMax();
    myArray.swap(0,myArray.getSize() - 1);
    myArray.removeLast();
    shiftDown(0);
    return max;
}
//See who the largest element is
public E findMax()
{
    if(myArray.getSize() == 0)
        throw new IndexOutOfBoundsException("heap is empty.");
    return myArray.getByIndex(0);
}
private void shiftDown(int index) {
    //If the left child of an element is greater than the total number, it ends
    while (leftChild(index) < myArray.getSize()) {
        //Compare with left child when right child is judged
        int swapIndex = leftChild(index); //Left child by default
        ////If there is a right child and the right child is older than the left child
        if (swapIndex + 1 < myArray.getSize() &&
                myArray.getByIndex(swapIndex).compareTo(myArray.getByIndex(swapIndex + 1)) < 0) {
            swapIndex = rightChild(index);
        }
        //The nature of the heap: as long as the current parent node is larger than the two-child node, you don't have to look down to end the loop directly
        if (myArray.getByIndex(index).compareTo(myArray.getByIndex(swapIndex)) > 0) {
            break;
        }
        myArray.swap(index, swapIndex);//Exchange elements with child nodes
        index = swapIndex;//Remark index position for next loop logic
    }
}

Replace operation

Replace is the replacement of the root element. The simple idea is to take out the root element, the extractMax() method implemented above, and then add an element.But this is equivalent to two O(logn) operations.Another idea is to simply replace the root element and make a shift down.

//Remove the root element and replace it with the latest one
public E replace(E e) {
    E e1 = findMax();
    myArray.set(0,e);
    shiftDown(0);
    return e1;
}

Heapify operation

heapify is the process of converting an array into a heap, which can be accomplished entirely by adding operations, but the complexity is O(nlogn) level. If you put an array in the heap once, find the last non-leaf node, traverse forward from this node, and do a sink operation on each element, you can.How do I locate the last non-leaf node?Simple is the parent of the last leaf node.

public MaxHeap(E[] arr){
    //Convert an array directly to the maximum heap
    myArray = new MyArray<>(arr);
    //Pare (arr.getSize - 1) is to start traversing up, except for the leaf nodes
    for(int x = parent(myArray.getSize() - 1); x >= 0 ; x--) {
        shiftDown(x);
    }
}

D-Fork Heap

A binary heap is a node with two sons, and a D-fork heap is a node with D sons, so the depth of the tree becomes shorter.Usage is similar to a binary heap, except that elements need to be judged as they rise and fall.As to how much D value is the best performance, it is still a practical try.

Posted by mahendrakalkura on Wed, 20 Nov 2019 23:07:41 -0800