-2

I am looking at a heap problem:

We are given a array with the index value in which we need to check if that index value in the array (i.e. the given heap tree) is in the correct position or not. If not then place the element at the correct position and this process is called heapify.

This is the example heap where values are modified:

heap

My code:

//min-heapify
#include<bits/stdc++.h>
using namespace std;

class minHeap{
    int *arr;
    int size;
    int capacity;
    public:
        minHeap(int c){
            size = 0;
            capacity = c;
            arr = new int[c];
        }

        int left(int i) { return (2 * i + 1); }
        int right(int i) { return (2 * i + 2); }
        int parent(int i) { return (i - 1) / 2; }

        //insert fun 
        void insert(int t){
            if(size == capacity) 
                return;
                
            size++;                   
            arr[size-1] = t;   

            for(int i=size-1;i!=0 && arr[parent(i)] > arr[i];){
                swap(arr[i],arr[parent(i)]);
                i = parent(i);
            }
        }

        //print array
        void print_array(){
            for(int i=0;i<size;i++){
                cout<<arr[i]<<" ";
            }
        }

        //min-heapify
        void minHeapify(int i){

            //finding the smallest among lc rc and current node
            int lc = left(i);   //left chid
            int rc = right(i);  //left child
            int smallest = i;

            //if left child exist and smaller then current
            if(lc<size && arr[lc] < arr[i]){ 
                smallest = lc;
            }
            //if right child exist and smaller then current
            if(rc<size && arr[rc] < arr[smallest]){
                smallest = rc;
            }

            //
            if(smallest!=i){ //
                swap(arr[smallest],arr[i]);
                minHeapify(smallest);
            }
        }

        //changes the value in array
        void edit(int index,int value){
            arr[index] = value;
        }

        //show the value at any index
        int show(int index){
            return arr[index];
        }
};

int main(){

    minHeap h(15);
    h.insert(40);
    h.insert(20);
    h.insert(30);
    h.insert(35);
    h.insert(25);
    h.insert(80);
    h.insert(32);
    h.insert(100);
    h.insert(60);
    h.insert(70);

    cout<<"perfect minHeap-->"<<endl;
    h.print_array();
    cout<<endl<<endl;

    cout<<"value changed (index 0 and 3)-->"<<endl;
    h.edit(0,40);
    h.edit(3,20);
    h.print_array();
    cout<<endl<<endl;

    cout<<"passing index of 0-->"<<endl;
    h.minHeapify(0);
    cout<<"function running...\n"<<endl;
    
    cout<<"Final Array after minHeapify-->"<<endl;
    h.print_array();
    cout<<endl;

    cout<<"left of 20 is :-";
    int index = h.left(1);
    cout<<h.show(index);

    return 0;
}

As you can see in my tree diagram and represented in array form, the output should be the same as a perfect minheap: we check the left of 20 to make sure we get 25.

The heap starts at index 0.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • 1
    I'm not getting the question? This is likely something you would figure out by stepping through the program line by line it in a debugger - or by printing out debugging hints to yourself in various places in the code. – Ted Lyngmo Dec 28 '21 at 05:45
  • Unlreated: Please read: [Why should I **not** `#include `?](https://stackoverflow.com/Questions/31816095/Why-Should-I-Not-Include-Bits-Stdc-H.) – Ted Lyngmo Dec 28 '21 at 05:48
  • I have not downvoted your question. I don't quite _understand_ the question, but that may just be me. If I'd thought that the question was _obviously_ unclear, I would have downvoted. That said, do not use ``. If you do when you post questions here, many people can't copy and compile your code. – Ted Lyngmo Dec 29 '21 at 17:17
  • @Ted Lyngmo -->then you first install "A COMPILER FOR C++ ", and then see the Benifits of standard library ..you dont want to use then dont use .i will use .. – vishal kumawat Dec 29 '21 at 17:25
  • I don't understand what you mean. `` is NOT a part of the standard library. Using it will mean you create non-portable programs. For reference: [C++ Standard Library headers](https://en.cppreference.com/w/cpp/header). If you continue to use it, people will continue to complain that they can't compile your programs. – Ted Lyngmo Dec 29 '21 at 17:27
  • I read it again and I still interpret it as you think it's a standard header - but it's not. I can pretty much guarrantee that if you use that header when taking a test when applying for a job, you will not get the job. – Ted Lyngmo Dec 30 '21 at 20:51

1 Answers1

3

This is expected behaviour. The minHeapify assumes that the children of the node at the given index are both heaps, but this is evidently not the case after having mutated the heap with those two edits. Consequently the result of calling minHeapify(0) is not guaranteed to be a heap.

To solve this, I would suggest that you alter the edit function so that it guarantees that it restores the heap immediately, and makes it unnecessary to make separate calls afterwards to restore the heap.

In order to do that I would first suggest to move the second part of the insert function into a separate siftUp function, so we can reuse that part:

    void insert(int t){
        if(size == capacity) 
            return;
            
        size++;                   
        arr[size-1] = t;   

        siftUp(size-1); // Defer this work to another function
    }

    void siftUp(int j) {
        for (int i = j; i != 0 && arr[parent(i)] > arr[i]; i = parent(i)) {
            swap(arr[i], arr[parent(i)]);
        }
    }

Then modify edit such that it either sifts the new value up or down, depending on how it is about to modify the current node's value:

    void edit(int index,int value){
        if (value < arr[index]) {
            arr[index] = value;
            siftUp(index);
        } else {
            arr[index] = value;
            minHeapify(index);
        }
    }

Now your heap will remain a valid heap even after making calls to edit. There is no more need to make an additional minHeapify call:

int main(){
    minHeap h(15);
    h.insert(40);
    h.insert(20);
    h.insert(30);
    h.insert(35);
    h.insert(25);
    h.insert(80);
    h.insert(32);
    h.insert(100);
    h.insert(60);
    h.insert(70);

    cout<<"perfect minHeap-->"<<endl;
    h.print_array();
    cout<<endl<<endl;

    cout<<"value changed (index 0 and 3)-->"<<endl;
    h.edit(0,40);
    h.edit(3,20);
    h.print_array();
    cout<<endl;

    return 0;
}

This code outputs at the end:

20 25 30 35 40 80 32 100 60 70

Which is this tree:

              20
             /  \
           25    30
         /   \   / \
        35   40 80  32
       / \   /
     100 60 70

...which is the final tree in the image you shared (except for a tiny difference at 60-70, which probably means you had those values inserted in reversed order -- but it is irrelevant for the question).

Why a single minHeapify(0) doesn't do the trick

When you edit the values in a heap without any further action, then the array no longer represents a heap. But h.minHeapify(0) can only guarantee to restore the heap when it is guaranteed that the children of node 0 are already heaps. Evidently this is not the case after the edit at index 3: the subtree rooted at index 1 is no longer a heap. And so a call to h.minHeapify(0) will not restore the heap property. minHeapify is an algorithm that only looks at a few nodes in the array, so it could never restore from just any edit in the array.

If you want the edits to not be accompanied by heap-correcting measures (by calling minHeapify or siftUp), then the only thing you can do after those edits is to rebuild the heap from scratch.

For that you can use the O(n) algorithm for turning any array into a heap:

    void buildHeap() {
        for (int i = (size - 1) / 2; i >= 0; i--)
            minHeapify(i);
    }        

In your driver code you should then replace the h.minHeapify(0) call with a call of h.buildHeap().

Note that this algorithm takes more time than a simple h.minHeapify(0) call.

A comment on your code:

int index = h.left(1);

This does not retrieve the left child of 20. This code looks at index 1 (not index 0), where the node's value is 25 (not 20).

trincot
  • 317,000
  • 35
  • 244
  • 286
  • still in your code also left of 20 is 35 ..ans should be 40 ..refer the diagram given – vishal kumawat Dec 28 '21 at 17:55
  • [link](https://i.stack.imgur.com/pq0Xg.png)**refer this** – vishal kumawat Dec 28 '21 at 17:56
  • your ans is also coming wrong ...left of 20 should be 40 and your is 35 – vishal kumawat Dec 28 '21 at 17:58
  • ` cout<<"left of 20 is :-"; int index = h.left(1); cout< – vishal kumawat Dec 28 '21 at 17:59
  • You write *"left of 20 should be 40"*. But that is not the case in your image. Your code is also wrong, because it doesn't print the left of the node with 20, since you pass index as 1, and at index 1 the node is not the node with 20, but with 25. The output I give is a **valid** heap and is actually the final one in your picture (except for a mismatch you have in the leaves 60 and 70). That's all that counts. The code I have posted makes 40 a right child of 25, just like in your picture. The heap property says that a parent must not be less than any of its children and that is the case here. – trincot Dec 28 '21 at 18:48
  • Can you come back to this? I don't understand why you say that the left of 20 should be 40. It is not what you have in the image, and it is not expected either... – trincot Dec 29 '21 at 08:10
  • you have called minheapify in the edit function only..i want that edit to only edit the value at the index and call minHeapify to the main after edit function call..and ya i called for index 1 it should be 0 if checkig for 20 ...can you edit the code and send me a final code in which minheapfy() to be called in the main. – vishal kumawat Dec 29 '21 at 16:57
  • Yes, I explained why I changed the `edit` functions. If you do not want that, then one call to `minHeapify(0)` cannot do the trick. I have added a section to my answer which explains why this cannot work. I hope it is clear. I have added an alternative, which is to apply the build-heap algorithm instead of calling `minHeapify(0)`. – trincot Dec 29 '21 at 19:32
  • okk you have done your work ..thanku – vishal kumawat Dec 30 '21 at 20:05