package _Sort.Algorithm
/**
* https://www.geeksforgeeks.org/heap-sort/
* https://www.cnblogs.com/chengxiao/p/6129630.html
*
* Heap Sort is an in-place algorithm. the typical implementation is not stable,but can be made stable.
* Time complexity of heapify is O(Logn), Time complexity of Create and BuildHelp is O(N) and overall
* time complexity of HeapSort is O(nLogn).
* Heap Sort is a comparision base sorting technique base on BinaryHeap data structure.
*
* ==Why array based representation for Binary Heap?
* Since Binary Heap is a Complete Binary Tree, it can easy represented as array and array based representation is
* space different.
* if the parent node is sorted at index I,the left child can be calculated by 2*I+1, and the right child can be calculated
* by 2*I+2 (assuming the indexing start at 0).
*
* MaxHeap: arr[i]>=arr[i*2+1] && arr[i]>=arr[i*2+2]
MinHeap: arr[i]<=arr[i*2+1] && arr[i]<=arr[i*2+2]
*
* ==Heap Sort algorithm for sorting in increasing order:
* 1. Build a Max or Min head from input array.
* 2. At this point, the largest item is sorted at the root of the heap. replace it with the last item of the
* heap followed by reducing the size of heap by 1. finally, heapify the root of tree.
* 3. repeat above steps while size of heap is greater than 1.
*
* ==How to build heap?
* Heapify procedure can be applied to a node only if its children nodes are heapified. so the heapification must
* be performed in the bottom up order.
*
* Lets understand with the help of an example:
*
* Input data: 4, 10, 3, 5, 1
4(0)
/ \
10(1) 3(2)
/ \
5(3) 1(4)
The numbers in bracket represent the indices in the array representation of data.
Applying heapify procedure to index 1:
4(0)
/ \
10(1) 3(2)
/ \
5(3) 1(4)
Applying heapify procedure to index 0:
10(0)
/ \
5(1) 3(2)
/ \
4(3) 1(4)
The heapify procedure calls itself recursively to build heap in top down manner.
* */
class HeapSort {
fun sort(array:IntArray){
val n = array.size
//build heap, bottom to up
for (i in n/2-1 downTo 0){
heapify(array,n,i)
}
//one by one extract an element from heap
for (i in n-1 downTo 1){
//move current node to end
val temp = array[0]
array[0] = array[i]
array[i] = temp
//call max heapify on the reduced heap
heapify(array,i,0)
}
printArray(array)
}
private fun printArray(array: IntArray) {
for (item in array) {
print("$item ,")
}
}
/**
*To heapify sub tree rooted with node i which is an index in array[].
* n is size of heap.
* */
private fun heapify(array: IntArray, n:Int, i:Int){
var largest = i
val left = 2*i+1
val right = 2*i+2
//if left child is largest than root
if (left < n && array[left] > array[largest]){
largest = left
}
//if right child is largest than root
if (right < n && array[right] > array[largest]){
largest = right
}
//if largest is not root
if (largest != i ){
val temp = array[i]
array[i] = array[largest]
array[largest] = temp
//recursively heapify the affected sub-tree
heapify(array,n,largest)
}
}
}