1

I have this code for heapSort which works fine. I also understand how the algorithm works when the start index is 1 and not 0. My question is that the maxheap method by itself below works for all indices greater than zero, but not at index 0. however the Sort method calls with index 0 and the array gets sorted. when index i = 0, the call to maxheap will have left=2*i=0 and right=2*i+1=1, which leads to i and left being same at 0 and right at index 1, meaning that the the root and left are same and has only right tree. this is confusing to me. Here is the code:

public class HeapSort 
{    
    private static int heapSize;

    /* Sort Function */
    public static void sort(int arr[])
    {       
        heapify(arr);     
        System.out.println("arrays is "+Arrays.toString(arr));
        for (int i = heapSize; i > 0; i--)
        {
            swap(arr,0, i);
            heapSize = heapSize-1;
            maxheap(arr, 0);
        }
    }     

    /* Function to build a heap */   
    public static void heapify(int arr[])
    {
        heapSize = arr.length-1;
        for (int i = heapSize/2; i >= 0; i--)
            maxheap(arr, i);      
        System.out.println("finished maxheap");
    }

    /* Function to swap largest element in heap */        
    public static void maxheap(int arr[], int i)
    { 
       //heapSize = arr.length-1;// comment this out if you use sort method since `heapSize` is defined at heapfy method
        int left = 2*i ;
        int right = 2*i + 1;
        int max = i;
        if (left <= heapSize && arr[left] > arr[i])
            max = left;
        if (right <= heapSize && arr[right] > arr[max])        
            max = right;
        //System.out.printf("i is %s; left is %s; right is %s; max is %s%n",i,left,right,max);
        if (max != i)
        {
            swap(arr, i, max);
            maxheap(arr, max);
        }
    }    

    /* Function to swap two numbers in an array */
    public static void swap(int arr[], int i, int j)
    {
        //System.out.println("called");
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp; 
    }    

    /* Main method */

    public static void main(String[] args) 
    {
        System.out.println("Heap Sort Test\n");
        /* Call method sort */
       int[] arr = {34,5,6,712,90};
        sort(arr);
       System.out.println("\nElements after sorting "); 
       System.out.println(Arrays.toString(arr)); 

     /* Call method maxheap; make sure you comment in heapSize=arr.length in the method */
        int[] arr2 = {2,1,3};
        maxheap(arr2, 1);
       //maxheap(arr2,0) will not work, i.e gives same arr2 as output
        System.out.println(Arrays.toString(arr2));
    }    

}

EDIT: These two blogs uses the same code: sanfoundry.com/java-program-implement-heap-sort, sciencetechpedia.blogspot.com/2012/11/heap-sort-using-java.html

eagertoLearn
  • 9,772
  • 23
  • 80
  • 122

2 Answers2

1

If your start index = 0 of your array, the method to calculate the left child index and the right child index should like this:

private static int getLeftCh (int index) {
    return index * 2 + 1;
}
private static int getRightCh (int index) {
    return index * 2 + 2;
}


[My Heapsort like this]
public class HeapSort {

// Heap sort the givenArray.
// Time complexity = O(nlgn).
// From max to min.
private static int getLeftCh (int index) {
    return index * 2 + 1;
}
private static int getRightCh (int index) {
    return index * 2 + 2;
}
private static void exchange (int[] givenArray, int firstIndex, int secondIndex) {
    int tempElem = givenArray[firstIndex];
    givenArray[firstIndex] = givenArray[secondIndex];
    givenArray[secondIndex] = tempElem;
}
private static void minHeapify (int[] givenArray, int size, int index) {
    int left = getLeftCh(index);
    int right = getRightCh(index);
    int minIndex = index;
    if (left < size && givenArray[left] <= givenArray[index]) minIndex = left;
    else minIndex = index;
    if (right < size && givenArray[right] < givenArray[minIndex]) minIndex = right;
    if (index != minIndex) {
        // Exchange the givenArray[index] and the givenArray[minIndex].
        exchange(givenArray, index, minIndex);
        // Do recrusion on from minIndex.
        minHeapify (givenArray, size, minIndex);
    }
}
private static void buildMinHeap (int[] givenArray) {
    int size = givenArray.length;
    for (int i = (size / 2 - 1); i >= 0; i --) {
        // Do min-heapify on the i.
        minHeapify (givenArray, size, i);
    }
}
public static void heapSortFromMaxToMin (int[] givenArray) {
    int size = givenArray.length;
    // Build the max heap.
    buildMinHeap(givenArray);

    // Do the max-heapify on the remaining part of the minheap.
    for (int i = size - 1; i >= 0; i --) {
        // Move the current first elem back to the last one among the current scope.
        exchange (givenArray, 0, size - 1);
        // Do minHeapify on the remaining part of the heap from the index = 0.
        minHeapify (givenArray, (-- size), 0);
    }
}

// Show array.
public static void showArray (int[] givenArray) {
    int size = givenArray.length;
    for (int i = 0; i < size; i ++)
        System.out.print(String.format("%-6d", givenArray[i]));
    System.out.println();
}


// Main method to test.
public static void main (String[] args) {
    // Test data: {5, 4, 8, 0, 2, -5, 8, 0}.
    int[] givenArray = {5, 4, 8, 0, 2, -5, 8, 0};

    // Test the heap sort on the givenArray, from max to min.
    heapSortFromMaxToMin (givenArray);
    showArray(givenArray);
}
}
zproject89
  • 225
  • 5
  • 19
0

When your array is 0-based, the child nodes are at (2*i)+1 and (2*i)+2.

To generalize, child nodes are at (2*i)+1-array_base and (2*i)+2-array_base.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • but the above code works with child nodes being `2*i and 2*i+1` when I do sorting on a 0-based array. It is when I call the `maxheap` method explicitly for index 0, it fails. however, the sort routine calls maxheap with index 0. so thats confusing as to how it works – eagertoLearn Feb 17 '14 at 21:29
  • @eagertoLearn: You already know that you have an error because your calculation of child indexes results in node 0 being his own left child. I showed you how to fix it. That some arrangements of items just happen to work only proves that you're getting lucky. Try rearranging the elements in the array you pass to `sort`. For example `int[] arr = {90,5,712,6,34};` and see what happens. – Jim Mischel Feb 17 '14 at 22:06
  • it works with different arrays inputs I tried, including the one you just gave. changing to what you suggested did not help when I call `maxheap(arr2,1)` which used to work previously. – eagertoLearn Feb 17 '14 at 22:30
  • @eagertoLearn: I don't know what you're trying to accomplish with your call to `maxheap(arr2, 1)`. The array you're passing isn't a valid heap, so any heap operation you try to perform on it will have unpredictable results. If you want to make it a heap, you have to call `heapify` first. That said, it's pretty obvious that you have at least one bug in your code: the calculation of child node indexes. Unless you fix that, you'll never be able to say whether there are other errors. – Jim Mischel Feb 17 '14 at 22:54
  • when I call `maxheap(arr2,1)`, it heapify any nodes from 1 and below. so with `int[] arr2 = {2,1,3};`, a call to `maxheap(arr2,1)` should give `[2, 3, 1]` and the above code gives this bit indeed. (a swap at index 1 and 2 has occured) because a parent node is always maximum). several other blogs uses the same indices as I have above; http://www.sanfoundry.com/java-program-implement-heap-sort/, http://sciencetechpedia.blogspot.com/2012/11/heap-sort-using-java.html. and above all I made a random 100 set of 100 integers and all of them gets sorted correctly. – eagertoLearn Feb 18 '14 at 01:03
  • @eagertoLearn: In your original question, you pointed out a bug in the code: that node 0 is its own left child. That the code works even spite of that bug is just luck. The pages you linked are just repetitions of somebody's broken heap code. If you want to *understand* how heaps work then you should be reading something else by somebody whose code doesn't have a known bug. I might suggest my short series on heaps, starting at http://blog.mischel.com/2013/09/26/priority-queues/. The samples are in C#, but the information you need is in the first two entries that don't have any code. – Jim Mischel Feb 18 '14 at 13:47
  • Thanks. I am reading through your blog, but I am just looking for a case where it fails. even in 100 different samples, if it did not fail, I really doubt that there is something wrong with the code – eagertoLearn Feb 18 '14 at 20:32