C++ different output using global variables vs passing variable thorugh function - c++

I was solving this question.
When the min and max variables are set as global variable, I'm getting the correct output, but when I pass them in the functions it messes up the output.
I can't figure out the reason. Can someone tell me, how are these two code snippets different.
global:
int min = 1,max = 0;
//dfs in which left subtree is travelled before right
void travLeft(Node * root, int i,vector<int> &left)
{
if(root==NULL) return;
if(i<min)
{
min = i;
left.push_back(root->data);
}
travLeft(root->left,i-1,left);
travLeft(root->right,i+1,left);
}
void travRight(Node * root, int i,vector<int> &right)
{
if(root==NULL) return;
if(i>max)
{
max = i;
right.push_back(root->data);
}
travRight(root->right,i+1,right);
travRight(root->left,i-1,right);
}
void topView(Node * root) {
vector<int> left,right;
travLeft(root,0,left);
travRight(root,0,right);
for(int i=left.size()-1;i>=0;i--)
{
cout<<left[i]<<" ";
}
for(int i=0;i<right.size();i++)
{
cout<<right[i]<<" ";
}
}
passing in the function :
//dfs in which left subtree is travelled before right
void travLeft(Node * root,int min, int i,vector<int> &left)
{
if(root==NULL) return;
if(i<min)
{
min = i;
left.push_back(root->data);
}
travLeft(root->left,min,i-1,left);
travLeft(root->right,min,i+1,left);
}
void travRight(Node * root,int max, int i,vector<int> &right)
{
if(root==NULL) return;
if(i>max)
{
max = i;
right.push_back(root->data);
}
travRight(root->right,max,i+1,right);
travRight(root->left,max,i-1,right);
}
void topView(Node * root) {
vector<int> left,right;
travLeft(root,INT_MAX,0,left);
travRight(root,0,0,right);
for(int i=left.size()-1;i>=0;i--)
{
cout<<left[i]<<" ";
}
for(int i=0;i<right.size();i++)
{
cout<<right[i]<<" ";
}
}

The global variable is global. The changes to the value will retain among all calls of travLeft and travRight.
On the other hand, the argument is local to the function. The new value of min and max are passed to the next level of recursion, but the update of min in the first recursion
travLeft(root->left,min,i-1,left);
will not passed to the second recursion
travLeft(root->right,min,i+1,left);
Because the same value of min, which is updated (or not updated and come from the previous level) at this level, is passed for the two calls.
The same thing will also happen with max and travRight.
This is the difference.

When using as global variables, the changes will take place(and retain the changes) through out all the layers. But, if you pass them to the function, for every recursion stage(layer) the variables will have certain values, which will remain unchanged for that particular layer.

#MikeCat and #SoumitraChatterjee has already stated the reason why your version that passes in the variable fail to work.
To make it work, you can alternatively set the parameter to take in min and max as references, so the changes will be reflexed to the original value:
void travLeft(Node* root, int& min, int i, vector<int> &left) { //... }
^^^^
Note that it might be tempting to set a default value to parameter max and min like:
// this doesn't work
// ↓ ↓ ↓ ↓ ↓ ↓
// void travLeft(Node* root, int i, vector<int> &left, int& min = 0)
However, this will not work because you are attempting to set min to a the reference of a temporary value, which does not work.
For more about that, consider: Default value to a parameter while passing by reference in C++

Related

Finding the height of a BST without returning anything from the function

I am trying to learn various data structures, and I am currently learning about trees, namely binary search trees. I have gotten most every function down, with the exception of the get height function. I found quite a lot of pseudo code on how to write this recursively, and returning the recursive path to find the height. This is what I came up with:
int getHeight(struct node* node)
{
if (node == nullptr)
return 0;
else
{
int leftDepth = getHeight(node->left);
int rightDepth = getHeight(node->right);
if (leftDepth > rightDepth)
return(leftDepth+1);
else return(rightDepth+1);
}
}
This is fine, but I wanted to stay consistent with how I wrote out my other functions. The other functions are templates, that each have a public wrapper function that is called in the driver. Then, this wrapper calls the private function that actually preforms the action that is intended. So, what I have for the get height is this:
template <typename T>
int binarySearch<T>::getHeight()
{
int height = 0;
getHeight(rootNode, height, 0);
return height;
}
template <typename T>
void binarySearch<T>::getHeight(Node *node, int &max, int layer)
{
int tempRight = 0;
int tempLeft = 0;
if (node == nullptr)
{
tempRight = -1;
tempLeft = -1;
max--;
}
else
{
if (node->left != nullptr)
{
tempLeft = 1;
getHeight(node->left, max, layer);
}
if (node->right != nullptr)
{
tempRight = 1;
getHeight(node->right, max, layer);
}
}
if (tempLeft > tempRight)
{
max++;
}
else
{
max++;
}
}
I intended to do something similar to a depth first search, in that I would increment a layer counter, to test to see if I am on the same layer, and if I am, to only increment the max counter once. I am a bit confused on the logical flow of the recursive get height, so my implementation makes little to no sense. Can someone point me in the right direction to information regarding the breakdown of the get height recursive function, or assist in correcting my poor attempt at doing what I intended? Thanks!
I'm not really sure, what you want to achieve, but here's a shot:
void getHeight(struct node* node, int &max, int layer) {
if (!node) return;
if (layer>max) {
max = layer;
}
getHeight(node->left, max, layer+1);
getHeight(node->right, max, layer+1);
}
You need to initialize max to 0 before calling getHeight.

Updating a pointer value with an integer during a recursive call in postorder traversal of a BST

int MovieTree::countMovieNodes()
{
int count = 0;
int* c = &count;
countMovieNodes(root,c);
return *c;
}
void MovieTree::countMovieNodes(MovieNode *node, int *c)
{
int count;
if(node == NULL)
{
return;
}
else
{
count ++;
countMovieNodes(node->leftChild, c);
countMovieNodes(node->rightChild, c);
}
}
My code is returning 0, so clearly I am misunderstanding the methodology to updating the pointer values. How do I fix this? I don't think my logic for post order traversal of the BST is the issue.
If you want to keep your current format, creating a new count is still making of copy of it, just incerment the pointer directly:
int MovieTree::countMovieNodes()
{
int count = 0;
int* c = &count;
countMovieNodes(root,c);
return *c;
}
void MovieTree::countMovieNodes(MovieNode *node, int *c)
{
if(node == NULL)
{
return;
}
else
{
++*c;
countMovieNodes(node->leftChild, c);
countMovieNodes(node->rightChild, c);
}
}
Your code doesn't actually use the c parameter (it just passes it on to recursive calls, which also don't use c). Your code also creates a local count variable in each call, which is only incremented (not written to or read from).
What you should do instead is
delete int count;
change count ++; to (*c)++; (or *c += 1; if you don't like parens) to increment the count variable in the top-level countMovieNodes() call)

How do I return value to main function without directly calling the function

I have multiple functions in my program. Each function has some conditions. If conditions are met, then it passes on the value to another function which again checks the value with some conditions, modifies it.
The first function [named 'squarefree()'] is called from main [obviously] and it further goes on to call another function which in course calls another function untill the process stops at last function named 'end()'. Like this:
#include <iostream>
using namespace std;
int squarefree(int n);
int goodnumber(int sf);
int end(int gn);
int main() {
// your code goes here
int l,r;
cin>>l;
cin>>r;
for(int p=l;p<=r;p++)
{squarefree(p);}
/*int ret=end(int gn); PROBLEM LIES HERE
cout<<ret; */
return 0;
}
int squarefree(int n){
int i;
for(int i=2;i<n;i++)
{
if((n%(i*i))==0)
{
cout<<"number not square free"<<endl;
break;
}
else{
cout<<"number square free"<<endl;
goodnumber(n);
break;
}
}
return 0;
}
int goodnumber(int sf){
cout<<"Sf is:"<<sf<<endl;
int s=0,c=0,flag=0;
for(int j=1;j<=sf;j++)
{
if(sf%j==0)
{
s+=j;
for(int k=2;k<=j/2;++k)
{
if(j%k==0)
{
c++;
}
}
}
}
cout<<"s is:"<<s<<endl;
cout<<"no.of prime numbers dividin s are:"<<c<<endl;
for(int l=2;l<=c/2;++l)
{
if(c%l==0)
{
flag=1;
break;
}
}
if (flag==0)
{cout << "C is a prime number, so this is good number and needs to be passed to next function"<<endl;
end(s);
}
else
{cout << "C is not a prime number"<<endl;
}
return 0;
}
int end(int gn)
{
int sum=0;
sum+=gn;
cout<<"SUm of factors of the good number is:"<<sum<<endl;
return sum;
}
The 'end()' function returns a value sum. Now I want this value sum to be updated everytime the for loop in main() function runs. For example: Sum in first iterations is 5, sum is 2nd iteration is 10, so total sum gets 15 and so on.
If somehow, the value returned by end function can be fetched into main function, that would be great.
Look at all those int-returning functions that are always returning 0. You might be able to take advantage of that.
A trivial example:
#include <iostream>
int step3(int val)
{
return val * val;
}
int step2(int val)
{
return step3(val + 1);
}
int step1(int val)
{
return step2(val * 2);
}
int main()
{
std::cout << step1(1);
}
But take care. You might find a case where you don't get any valid results and need to inform the caller that no result was found.
In addition to the idea of having the functions return the result of the next stage in the pipeline, which is an excellent idea, you can pass the address of the variable in which to store the result (allowing you to return more than one result, or an error code), or store the result of each stage in a temporary variable and return that (allowing you to use a result in more than one computation). I would advise against using a global variable to bypass the stack; it’s considered poor practice.
Some Examples:
// Returning the result of the next stage in the pipeline:
int g(int);
int f(int x)
{
return g(x);
}
// Passing a variable by reference:
enum errcode { success, failure };
errcode sqr( int input, int& output )
{
output = input * input; // This modifies the second variable the caller gave.
return success;
}
// Storing in a temporary variable:
int stage2(int);
int stage1(int x)
{
const int y = stage2(x); // Store the result in a temporary.
const int z = sqr(y);
return z;
}
// Passing results through a global variable is a bad idea:
int necessary_evil = 0; // Declared in global scope; should at least be
// declared static if possible to make it visible only in this source file.
// Namespaces are a fancier way to do something similar.
void kludge(int x)
{
necessary_evil = x * x; // The caller will check the global.
return;
}
There are examples of all of these in the standard library: printf() is essentially a wrapper for vfprintf(), strtol() takes a parameter by reference that the function sets to a pointer to the remainder of the string, and errno is a global variable.

Implementing min function

Good day, I found this priority queue implementation and I am trying to get a min version of it (instead of max). I have no idea where to start. I tried mixing the signs of the functions (naive attempt) but it didn't get me far. Any help of how to implement it and a few words explaining it are very wellcome. The source is below:
Note I have left it's comments
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;
class PriorityQueue
{
vector<int> pq_keys;
void shiftRight(int low, int high);
void shiftLeft(int low, int high);
void buildHeap();
public:
PriorityQueue(){}
PriorityQueue(vector<int>& items)
{
pq_keys = items;
buildHeap();
}
/*Insert a new item into the priority queue*/
void enqueue(int item);
/*Get the maximum element from the priority queue*/
int dequeue();
/*Just for testing*/
void print();
};
void PriorityQueue::enqueue(int item)
{
pq_keys.push_back(item);
shiftLeft(0, pq_keys.size() - 1);
return;
}
int PriorityQueue::dequeue()
{
assert(pq_keys.size() != 0);
int last = pq_keys.size() - 1;
int tmp = pq_keys[0];
pq_keys[0] = pq_keys[last];
pq_keys[last] = tmp;
pq_keys.pop_back();
shiftRight(0, last-1);
return tmp;
}
void PriorityQueue::print()
{
int size = pq_keys.size();
for (int i = 0; i < size; ++i)
cout << pq_keys[i] << " ";
cout << endl;
}
void PriorityQueue::shiftLeft(int low, int high)
{
int childIdx = high;
while (childIdx > low)
{
int parentIdx = (childIdx-1)/2;
/*if child is bigger than parent we need to swap*/
if (pq_keys[childIdx] > pq_keys[parentIdx])
{
int tmp = pq_keys[childIdx];
pq_keys[childIdx] = pq_keys[parentIdx];
pq_keys[parentIdx] = tmp;
/*Make parent index the child and shift towards left*/
childIdx = parentIdx;
}
else
{
break;
}
}
return;
}
void PriorityQueue::shiftRight(int low, int high)
{
int root = low;
while ((root*2)+1 <= high)
{
int leftChild = (root * 2) + 1;
int rightChild = leftChild + 1;
int swapIdx = root;
/*Check if root is less than left child*/
if (pq_keys[swapIdx] < pq_keys[leftChild])
{
swapIdx = leftChild;
}
/*If right child exists check if it is less than current root*/
if ((rightChild <= high) && (pq_keys[swapIdx] < pq_keys[rightChild]))
{
swapIdx = rightChild;
}
/*Make the biggest element of root, left and right child the root*/
if (swapIdx != root)
{
int tmp = pq_keys[root];
pq_keys[root] = pq_keys[swapIdx];
pq_keys[swapIdx] = tmp;
/*Keep shifting right and ensure that swapIdx satisfies
heap property aka left and right child of it is smaller than
itself*/
root = swapIdx;
}
else
{
break;
}
}
return;
}
void PriorityQueue::buildHeap()
{
/*Start with middle element. Middle element is chosen in
such a way that the last element of array is either its
left child or right child*/
int size = pq_keys.size();
int midIdx = (size -2)/2;
while (midIdx >= 0)
{
shiftRight(midIdx, size-1);
--midIdx;
}
return;
}
int main()
{
//example usage
PriorityQueue asd;
asd.enqueue(2);
asd.enqueue(3);
asd.enqueue(4);
asd.enqueue(7);
asd.enqueue(5);
asd.print();
cout<< asd.dequeue() << endl;
asd.print();
return 0;
}
Well generally in such problems, i.e. algorithms based on comparison of elements, you can redefine what does (a < b) mean. (That is how things in standard library work by the way. You can define your own comparator.)
So if you change it's meaning to the opposite. You will reverse the ordering.
You need to identify every comparison of elements, and switch it. So for every piece of code like this
/*if child is bigger than parent we need to swap*/
if (pq_keys[childIdx] > pq_keys[parentIdx])
invert it's meaning/logic.
Simple negation should do the trick:
/*if child is NOT bigger than parent we need to swap*/
if !(pq_keys[childIdx] > pq_keys[parentIdx])
You do not even need to understand algorithm. Just inverse meaning of what lesser element is.
Edit:
Additional note. You could actually refactor it into some kind of bool compare(T a, T b). And use this function where comparison is used. So whenever you want to change the behaviour you just need to change one place and it will be consistent. But that is mostly to avoid work to look for every such occurrence, and stupid bugs and when you miss one.
Easier:
std::prioroty_queue<int, std::vector<int>, std::greater<int>> my_queue;
If this is part of an exercise, then I suggest following the standard library's design principles: split the problem up:
data storage (e.g. std::vector)
sorting or "heapifying" algorithm (c.f. std::make_heap etc.)
ordering criteria (to be used by 2. above)
Your class should give you some leeway to change any of these independently. With that in place, you can trivially change the "less-than" ordering for a "greater than" one.

maintaining a recursion count

I'm trying to count the number of calls within a recursive permutation function.
I've written a function that fills a queue with all the permutations but I can't seem to figure out how to maintain an accurate count.
Ultimately i'd like the function to return a subset of the permuatations specified by lbound and ubound arguments, and to do so I think i need someway to keep an internal count.
Using the size of the returned queue will not work since i'd like the function to be able to handle permutations too big to hold in memory.
For this code i'd like the count to be returned as 100.
#include <vector>
#include <iostream>;
using namespace std;
int& Permutations(vector<vector<int>> param, vector<vector<int>> &perm, int index=0)
{
static vector<int> iter;
static int count = 0;
if (index == param.size())
{
perm.push_back(iter); // add permutation to queue
count++;
return count;
}
for (int i=param[index][0]; i<=param[index][1]; i+=param[index][2])
{
if (iter.size() > index) iter[index] = i;
else iter.push_back(i);
Permutations(param, perm, index+1); // recursive function
}
}
void main()
{
vector<vector<int>> params; // vector of parameter vectors
vector<int> param1, param2;
int arr1[3] = {0,9,1}; // range for each parameter vector
int arr2[3] = {0,9,1}; // specified as lbound, ubound, step
param1.insert(param1.end(),arr1,arr1+3);
param2.insert(param2.end(),arr2,arr2+3);
params.push_back(param1);
params.push_back(param2);
vector<vector<int>> queue; // queue of generated permutations
int permcount = Permutations(params,queue);
cout << "the permutation count is " << permcount << endl;
cin.get();
}
Using a static count will not work, because it's not going to ever be reset (and will cause problems if you ever go multi-threaded).
Instead, how about this:
int Permutation(/* params */)
{
int count = 1; // Count ourself
for (whatever)
{
count += Permutation(whatever); // Count cumulative sum from recursion
}
return count;
}
Each call to Permutation() returns the total number of calls that were made below it in the call tree. As we unwind, all the counts from the sub-trees get summed together, to eventually produce the final return value.
int foo(int count,/*Other Params*/) {
/*Calucation*/
if (!terminatingCondition) {
foo(count++,/*Other Params*/);
}
logger.log("foo was called " + count + "times");
return /*calcualtion*/;
}
I'm just trying to answer the question by ignoring your actual algorithm purpose. The two statics should be moved to argument references, or you don't have a good way to reset their values.
void Permutations(vector<vector<int>> param, vector<vector<int>> &perm, vector<int> &iter, int &count, int index=0)
{
++count;
// ...
}