James MV
James MV

Reputation: 8727

Heap Sort down heap method not working?

I've really been pulling me hair out on this for a while and would literally die for some answers on this.

I have a array based implementation of a heap. My up heap sort on insertion seems to be working, but I can't get the down heap sort to work when I pop the top value. I've put the full code together here and would love it if someone could correct the downHeap method so that it is able to sort this array when removing the top value:

public class HeapSortArray {
static int sizeOfTree = 0; 

    private static int arrayBufferSize = 50;

    public static int[] heap = new int[arrayBufferSize];
    static int[] numbers = new int[]{ 0, 7, 9, 7, 5, 2, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };


    public static void main(String[] args) {
        insert(0);  //set 0 of the array to nothing

        //fill array with numbers
        for (int i = 1; i < numbers.length; i++) {

            insert(numbers[i]);
          if (i > 1) {
            upHeap(i);
          }
        }
        System.out.println("Heap Printed once inserted: ");
        for(int i=1; i < numbers.length; i++){
            System.out.println(heap[i]);
        }
        System.out.println("----------------------");
        System.out.println("Heap Printed as top value is popped out: ");
        //pop lowest value 
        for(int i = numbers.length; i != 1; i--){
             removeMin();
            }

    }




    public static void upHeap(int childLocation) {      

        int parentLocation = childLocation / 2;
        int child = childLocation;
        int parentTemp = heap[parentLocation];
        int childTemp = heap[childLocation];

        int parentValue = heap[parentLocation];
        int childValue =  heap[child];

        if (parentValue > childValue) {
            heap[parentLocation] = childTemp;
            heap[childLocation] = parentTemp;
        }
        if (parentLocation != 1) {
            upHeap(parentLocation);
        }
      }


    public static void downHeap(int location){

        if(location > 0){


            int parentLocation = location;
            int leftchildLocation = 2*location;
            int rightchildLocation = 2*location+1;


            int parentValue = heap[parentLocation];
            int leftchildValue = heap[leftchildLocation];
            int rightchildValue = heap[rightchildLocation];


            int parentTemp = heap[parentLocation];
            int leftChildTemp = heap[leftchildLocation];
            int rightChildTemp = heap[rightchildLocation];

            if(leftchildValue < rightchildValue && leftchildValue < parentValue){
                heap[parentLocation] =  leftchildValue;
                heap[leftchildLocation] = parentTemp;
                downHeap(leftchildLocation);
            }

            if(rightchildValue < leftchildValue && rightchildValue < parentValue){
                heap[parentLocation] =  rightchildValue;
                heap[rightchildLocation] = parentTemp;
                downHeap(rightchildLocation);
            }

        }

    }

    public static int removeMin() {

        sizeOfTree--;

        if(sizeOfTree > 1){
        heap[1] = heap[sizeOfTree];

        downHeap(1);
        }
        int toReturn = heap[1];
        System.out.println(toReturn);

        return toReturn;
    }

    public static void insert(int toInsert) {

        heap[sizeOfTree] = toInsert;    


    if(sizeOfTree > 1){
            upHeap(sizeOfTree);
            }


            sizeOfTree++;

        }

}

Many thanks to anyone who can shed some light on this one.

Edit: The above implementation will work if on line 38 this:

int parentLocation = childLocation / 2;

is changed to:

int parentLocation = childLocation -1;

I know that the second method is just not the way its meant to be done, but why does my childLocation / 2 not give me the parent as it should?

Upvotes: 1

Views: 7346

Answers (1)

Wyn07
Wyn07

Reputation: 56

Here are the checks necessary in downHeap:

  1. The location must be within the size of the heap
  2. Is the right child within the size of the heap AND is the right child smaller than the left child and the parent
  3. Otherwise, is the left child within the size of the heap AND is the left child smaller than the parent

    public static void downHeap(int location){
    if(location < sizeOfTree){
        int p = location;
        int l = 2*p;
        int r = 2*p+1;
        int s = sizeOfTree;
        if(r<s && heap[r]<heap[p] && heap[r]<heap[l]){
            int temp = heap[r];
            heap[r] = heap[p];
            heap[p] = temp;
            downHeap(r);
        }else if(l<s && heap[l]<heap[p]){
            int temp = heap[l];
            heap[l] = heap[p];
            heap[p] = temp;
            downHeap(l);
        }
    }}
    

Also in removeMin(), you should be copying the min value before overwriting it:

    public static int removeMin() {
    sizeOfTree--;
    int toReturn = heap[1];
    if(sizeOfTree > 1){
        heap[1] = heap[sizeOfTree];
        downHeap(1);
    }
    System.out.println(toReturn);
    return toReturn;
}

Upvotes: 4

Related Questions