Heap Sort


  • Time Complexity - O(nlogn)
  • We use min-heap if we want to sort in ascending order and max heap if we want to sort in descending order.
  • We insert one by one into the heap, heapifying  from bottom to top while inserting in order to maintain corresponding heap property.
  • Now, after all elements are insered into the heap, we extract elements one by one.
  • Remember- we can only extract the root of a heap. 
  • Also, after extraction, we put the last element in the level order traversal of heap as the new root and again heapify from top to bottom this time, in order to maintain the corresponding heap property.
  • It is not a stable sort

__________________________________________________________________________________________________________________________________________________________________



public class Main {
    int[] heapArr;
    int endOfHeap;
    
    Main(int size){
        this.heapArr=new int[size];
        this.endOfHeap=0;
    }
    
    public void initializeHeapArr(){
        if(this.endOfHeap==0){
            for(int i=0;i<this.heapArr.length;i++){
                this.heapArr[i]=Integer.MIN_VALUE;
            }
        }
    }
    
    public void levelOrderTraversal(){
        if(this.endOfHeap==0){
            System.out.println("Heap is empty, can't traverse");
            return;
        }
        for(int i=1;i<=this.endOfHeap;i++){
            System.out.print(this.heapArr[i]+" ");
        }
        System.out.println();
    }
    
    public void insertIntoHeap(int data){
        if(this.endOfHeap==(this.heapArr.length-1)){
            System.out.println("Heap is full, can't insert '"+data+"'");
            return;
        }
        endOfHeap++;
        this.heapArr[this.endOfHeap]=data;
        
        // now heapify bottom to top
        
        // first we have to find its parent
        int currentParentIndex= -1; // if left children then parent index will be (children's index /2) and if right child (children's index -1 /2). In any case (children's index /2) will give us parent index as Java will round it off
        int currentChildIndex = this.endOfHeap;
        
        while(currentChildIndex>=1){
            currentParentIndex = currentChildIndex/2;
            if(this.heapArr[currentChildIndex]<this.heapArr[currentParentIndex]){
                // move up or swap
                int temp = this.heapArr[currentChildIndex];
                this.heapArr[currentChildIndex] = this.heapArr[currentParentIndex];
                this.heapArr[currentParentIndex]=temp;
            }
            else{
                break;
            }
            currentChildIndex = currentParentIndex;
        }
    }
    
    public int extractMinFromHeap(){
        if(this.endOfHeap==0){
            System.out.println("Can't extract node, as heap is empty");
            return Integer.MIN_VALUE;
        }
        int minValue = this.heapArr[1];
        
        // now make the last node in level order traversal of binary heap as the new root of binary heap
        this.heapArr[1]=this.heapArr[this.endOfHeap];
        // now delete the last node, as we have promoted it to be the new root
        this.heapArr[this.endOfHeap]=Integer.MIN_VALUE;
        this.endOfHeap--;
        
        
        // Now heapify from top to bottom
        int currentParentIndex=1;
        
        
        // find which child of the two is minimum, the child having the minimum value will become the candidate for swap if it has value less than root obviously
        while(currentParentIndex<this.endOfHeap){
            
            int currentChildIndex=-1;
            
            int leftChildIndex = 2*currentParentIndex;
            int rightChildIndex = (2*currentParentIndex)+1;
            
            int leftChildValue=Integer.MIN_VALUE;
            int rightChildValue = Integer.MIN_VALUE;
            
            if(leftChildIndex <= this.endOfHeap){
                leftChildValue=this.heapArr[leftChildIndex];
            }
            if(rightChildIndex <= this.endOfHeap){
                rightChildValue = this.heapArr[rightChildIndex];
            }
            
            // if no child is there
            if(leftChildValue==Integer.MIN_VALUE && rightChildValue== Integer.MIN_VALUE) {
            break;
            }
            // if left child is not there
            if(leftChildValue==Integer.MIN_VALUE && rightChildValue!= Integer.MIN_VALUE){
                currentChildIndex=rightChildIndex;
            }
            // if right child is not there
            else if(rightChildValue==Integer.MIN_VALUE && leftChildValue!=Integer.MIN_VALUE){
                currentChildIndex=leftChildIndex;
            }
            // if both child is present
            else{
                if(leftChildValue<=rightChildValue){
                    currentChildIndex = leftChildIndex;
                }
                else{
                    currentChildIndex = rightChildIndex;
                }
            }
            
            if(this.heapArr[currentParentIndex]>this.heapArr[currentChildIndex]){
                int temp = this.heapArr[currentParentIndex];
                this.heapArr[currentParentIndex]=this.heapArr[currentChildIndex];
                this.heapArr[currentChildIndex]=temp;
            }
            else{
                break;
            }
            currentParentIndex=currentChildIndex;
            
//            levelOrderTraversal();
        }
//        System.out.println();
        return minValue;
    }
    
    public static void main(String[] args) throws Exception {
        Main minHeap = new Main(15);
        minHeap.initializeHeapArr();
        minHeap.levelOrderTraversal();
        
        int[] arr={1,4,4,5,6,2,3,90,120,43,0};
        System.out.println("UnSorted Array :");
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
        
        for(int i=0;i<arr.length;i++){
            minHeap.insertIntoHeap(arr[i]);
        }
        System.out.println();
        System.out.println("Min Heap initial Level order traversal...");
        minHeap.levelOrderTraversal();
        
        // System.out.println("extractMinFromHeap...");
        // System.out.println(minHeap.extractMinFromHeap());
        // System.out.println();
        // System.out.println("Level order traversal...");
        // minHeap.levelOrderTraversal();
        
        // for(int i=0;i<arr.length;i++){
        //     arr[i]=minHeap.extractMinFromHeap();
        // }
        
        System.out.println("Sorted Array :");
        for(int i=0;i<arr.length;i++){
            System.out.print(minHeap.extractMinFromHeap()+" ");
        }
    }
}


Output: 

Heap is empty, can't traverse
UnSorted Array :
1 4 4 5 6 2 3 90 120 43 0 
Min Heap initial Level order traversal...
0 1 2 5 4 4 3 90 120 43 6 
Sorted Array :
0 1 2 3 4 4 5 6 43 90 120 

Comments

Popular posts from this blog

Binary Heap - Introduction

Divide and Conquer - Introduction

Bubble Sort