Following code for max-heap implementation
#include<iostream>
#include<math.h>
using namespace std;
#define maxn 1000
int x[maxn];
int parent(int i){
return int(i/2);
}
int left(int i){
return 2*i;
}
int right(int i){
return 2*i+1;
}
void max_heap(int x[],int i,int size){
int largest;
int l=left(i);
int r=right(i);
if (l<=size && x[l]>x[i]){
largest=l;
}
else
{
largest=i;
}
if (r<=size && x[r]>x[largest]){
largest=r;
}
if (largest!=i) { int s=x[i];x[i]=x[largest];x[largest]=s;}
max_heap(x,largest,size);
}
int main(){
x[1]=16;
x[2]=4;
x[3]=10;
x[4]=14;
x[5]=7;
x[6]=9;
x[7]=3;
x[8]=2;
x[9]=8;
x[10]=1;
int size=10;
max_heap(x,2,size);
for (int i=1;i<=10;i++)
cout<<x[i]<<" ";
return 0;
}
When I run it, it writes such kind of warning:
1>c:\users\datuashvili\documents\visual studio 2010\projects\heap_property\heap_property\heap_property.cpp(36): warning C4717: 'max_heap' : recursive on all control paths, function will cause runtime stack overflow
Please tell me what is wrong?
The message tells you exactly what's wrong. You haven't implemented any checks to stop the recursion. One smart compiler.
max_heap function doesn't have base case, i.e., a return statement. You are just recursively calling the function but never saying when to break another successive call to the max_heap.
Also, in your example you are just calling the function with out satisfying any condition. Usually recursion is done or not done when a case is satisfied.
please tell me what is wrong?
Another problem that I see is that the size of your array x is 10. But the indices that you are using to set values are 1-10.
Put
max_heap(x,largest,size);
inside last check, like this:
if (largest!=i)
{
int s=x[i];
x[i]=x[largest];
x[largest]=s;
max_heap(x,largest,size);
}
and you're done!
There are many other problems with your code, but to answer your specific question, above change would do!
Related
This is part of a debugging assignment that I've been stuck on for days. I'm not as much looking for an answer as much as I'm looking for where to look to find the answer.
I have a function that takes an int as a parameter, and the test uses that function to calculate the sum of the range (0,n]. My problem is that I am new to C++ and have exhausted my knowledge of where to look to solve this. Any help would be greatly appreciated.
Also, it goes without saying that I cannot modify the test file.
Header.h
bool getNum(int n);
Header.cpp:
bool getNum(int n)
{
n = n + 1;
if (n < 10)
{
return true;
}
else
{
return false;
}
}
Test.cpp
int n = 0;
int sum = 0;
while (getNum(n) && n)
{
sum += n;
}
CHECK(sum == 45);
My problem is that I have no way of getting n to be true to pass the logical &&, so the test never visits the inside of the while loop.
You can change the value of an argument to a function, by taking that argument as a reference:
bool getNum(int &n) // note the reference parameter
{
// changes to n are visible to the caller of this function
}
You have to change the declaration of getNum to match as well, of course.
Note that there is no change to the calling code.
Here's a demo of a working example.
i did exactly what the pseudo code told me in the book introduction to algorithms and it didn't work
there are two parts that i dont really understand
1-how do u make a recursive function that is a void i mean shouldnt a recursive function always return the last step then what is before it .. it's a void so how would it preform the task
2-merg_sor() was called twice in one function .. do u call that nested recursion ?or what ?? .. and how does it affect the merg function
#include <iostream>
#include <vector>
using namespace std;
void Merg(vector<int> Arr,int start,int middle,int end)
{
std::vector<int> left;
std::vector<int> right;
for(int i =start;i<(end-start);i++)
{
if (i <middle)
{
right.push_back(Arr.at(i));
}
else
{
left.push_back(Arr.at(i));
}
}
int j=0;
int k=0;
for(int i =start;i<(end-start);i++)
{
if(right.at(j)<=Arr.at(i))
{
Arr.at(i)=right.at(j);
j++;
}
else
{
Arr.at(i)=left.at(k);
k++;
}
}
}
void Merg_sort(vector<int> Arr,int start,int end)
{
if (start <end)
{
int middle = (start+end)/2;
Merg_sort(Arr,start,middle);
Merg_sort(Arr,middle+1,end);
Merg(Arr,start,middle,end);
}
}
int main()
{
vector<int> x;
for (int i =0;i<8;i++){x.push_back(i);}
x.at(2)=8;
Merg_sort(x,0,7);
}
1-how do u make a recursive function that is a void i mean shouldnt a recursive function always return the last step then what is before it .. it's a void so how would it preform the task
A function can have side effects. It means, that a function can modify the state of the program. A void function always works by side effects. A void function that doesn't have side effects is completely useless. Whether the function is recursive makes no difference to this question.
2-merg_sor() was called twice in one function .. do u call that nested recursion ?or what ??
I'm not sure if it is commonly used term, but I would describe it as multi-branched recursion.
2 .. and how does it affect the merg function
It doesn't, because it has no side effects.
i did exactly what the pseudo code told me
Perhaps you didn't interpret the pseudo code correctly. Perhaps the arguments are implicitly references in the pseudo-language that you're reading such as they are in languages like python.
I have written the following randomized quicksort code using tail recursion. I wanted to see the effect of not using tail recursion and wanted to see how the time of execution and run time are affected. How can we remove tail recursion from the below randomized quicksort code?
#include<iostream>
#include<cstdlib>
using namespace std;
int partition(int low,int high,int a[])
{
int index=(rand()%(high-low))+low;
//cout<<endl<<index<<"----"<<endl;
int temp1=a[index];
a[index]=a[low];
a[low]=temp1;
int left,right,pivot_item=a[low];
left=low;
right=high;
while(left<right)
{
while(a[left]<=pivot_item)
left++;
while(a[right]>pivot_item)
right--;
if(left<right)
{
int temp=a[right];
a[right]=a[left];
a[left]=temp;
}
}
a[low]=a[right];
a[right]=pivot_item;
return right;
}
void quicksort(int low,int high,int a[])
{
int pivot;
if(low<high)
{
pivot=partition(low,high,a);
quicksort(low,pivot-1,a);
quicksort(pivot+1,high,a);
}
}
int main()
{
srand(time(NULL));
int n;
n=50;
int a[n];
int i;
for(i=0;i<n;i++)
a[i]=(rand()%(1000-1));
quicksort(0,n-1,a);
cout<<endl;
for(i=0;i<n;i++)
cout<<a[i]<<endl;
return 0;
}
EDIT:
Is there any way to altogether remove the second recursive call in the quicksort function. This would mean removing tail recursion and would also significantly affect the time.
A simple way to remove tail recursion is to do something else in the function after making the recursive call. Below I've changed the function to return a value instead of void, and added a return statement to rturn something after the recursive call is finished. This should have minimal performance impact.
int quicksort(int low,int high,int a[])
{
int pivot;
if(low<high)
{
pivot=partition(low,high,a);
quicksort(low,pivot-1,a);
quicksort(pivot+1,high,a);
}
return 0;
}
Compilers typically have an option to enable and disable particular optimizations.
In case of g++ and related compilers, you can enable and disable tail call optimization using -foptimize-sibling-calls and -fno-optimize-sibling-calls options. If you use another compiler, see the manual.
I would recommend using these to compare the effect of tail recursion, because it allows you to use the same algorithm.
Quicksort is naturally tail recursive, so it's not simple to make non-tail-recurive. One one hand, it's easy: simply do something after the recursion call. VoilĂ , the algorithm is now no longer tail recursive. But, what you do after the recursion is important. It must have a side-effect, or else it can be optimized away. But then it would affect the performance and you're no longer measuring only the effect of the tail call optimization.
Here is an idea. Implement two identical functions that call each other instead if themselves in the tail call:
void quicksort1(int low,int high,int a[])
{
int pivot;
if(low<high)
{
pivot=partition(low,high,a);
quicksort1(low,pivot-1,a);
quicksort2(pivot+1,high,a);
}
}
void quicksort2(int low,int high,int a[])
{
int pivot;
if(low<high)
{
pivot=partition(low,high,a);
quicksort2(low,pivot-1,a);
quicksort1(pivot+1,high,a);
}
}
It's still possible to do tail call optimization on mutually recursive functions, so I won't guarantee that a smart compiler won't figure out what's going on. But the optimization will be harder to implement, so some compilers might not attempt to do it. Check the assembly if you want to be sure. Also, this may have some effect on instruction cache, so it may have an effect on performance other than just disabling the tail call optimization.
Can someone tell me what is wrong with this code?!
visual studio tells the operand of * must be a pointer...
(in line that we call operation)...
can someone tell how exactly declaring an array of pointer to functions is?
I'm really confused.
#include<iostream>
#include<conio.h>
using namespace std;
int power(int x)
{
return(x*x);
}
int factorial(int x)
{
int fact=1;
while(x!=0)
fact*=x--;
return fact;
}
int multiply(int x)
{
return(x*2);
}
int log(int x)
{
int result=1;
while(x/2)
result++;
return result;
}
//The global array of pointer to functions
int(*choice_array[])(int)={power,factorial,multiply,log};
int operation(int x,int(*functocall)(int))
{
int res;
res=(*functocall)(x);
return res;
}
int main()
{
int choice,number;
cout<<"Please enter your choice : ";
cin>>choice;
cout<<"\nPlease enter your number : ";
cin>>number;
cout<<"\nThe result is :"<<operation(number,(*choice_array[choice](number)));
}
This call
operation(number, (*choice_array[choice](number)))
is invalid.
You have to supply a pointer to a function as second argument. Either write
operation(number, choice_array[choice] )
or
operation(number, *choice_array[choice] )
The problem is that (*choice_array[choice](number)) isn't a function itself but a result of function call.
Did you mean (*choice_array[choice])?
operation takes a function as argument, but (*choice_array[choice](number)) is an int, cuz it's applying choice-array[choice] to number
just do operation(number, choice_array[choice])
EDIT : don't want to say something wrong, but it seems to me that
*(choice_array[choice])
(choice_array[choice])
are the same, (meaning pointer to the function IS (can be used as a call to) the function, and you cant "dereference" it)
Here I have written some code to get the square of a number from a function, but the return statement is not working as desired by me, it is giving me the same number which I have entered, I want to know the reason behind this, please if any one can explain this to me...
#include<iostream>
#include<conio.h>
using namespace std;
int square(int &i);
int main()
{
cout<<"enter the number whose square you want to find";
int a;
cin>>a;
square(a);
cout<<"the square of the number is"<<a;
_getch();
return 0;
}
int square(int &i)
{
return i*i;
}
You're ignoring the returned value. You should store it as:
int value = square(a);
cout<<"the square of the number is "<< value;
Also, as the type is just integral type, passing by reference doesn't give you much advantage. I would suggest to use pass by value for its readability sake:
int square(int i)
{
return i*i;
}
--
Or in case if you're experimeting with reference, and trying to learn it, then in that case I would say that you've to store the result of product in the argument itself, as:
int square(int &i)
{
i = i * i; //this updates i here, and at the call site as well
return i;
}
Or simply do this:
int square(int &i)
{
return i = i*i; //multiply, update, and return - all in one statement!
}
You do not obtain the result.
Your line should be:
a = square(a);
to fetch the result from the function.
The other possibility would be to write in the function
int square(int &i)
{
i = i * i;
return i;
}
The latter will alter the variable you passed to the function which justifies passing a reference.
To make it clear you want to alter the variable do something like:
void square(int &i)
{
i = i * i;
}
You see there is no return involved but it will alter the variables value.
You have a choice:
Modify the parameter you pass in, or
Return a value and assign it to something in the calling scope.
What you are doing in square is the second option. You seem to want the first.
If what you really want is to modify the passed-in value, then what you need is this:
void square(int &i)
{
i = i*i;
}
Either do it this way:
a = Square (a) ; // in main()
...
int Square (int i) // Pass by value -- doesn't change a in main
{
return i * i ;
}
or do it this way:
Square (a) ; // in main()
...
void Square (int& i) // Pass by reference -- changes a in main
{
i = i * i ; // No need for a return value
}
Make sure you understand the difference before you program anything else!
Judging by your comments on the answers, you've misunderstood what passing by reference does OR you've misunderstood return.
I'm assuming you're thinking that the variable i will be updated in your program. However, this is not the case. If you did something like...
i = i*i;
then yes, you would be correct. However, you did not assign any value to i, you simply multiplied it by itself and returned the result. Also, if you truly wanted to make this work based on a reference, there would be no need to return anything, as the variable would be updated via the reference.