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

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)

Related

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

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++

search function causes program to crash

I have been going through the debugger but can't seem to pinpoint exactly what is going wrong. I have come to my own conclusion i must be missing a nullptr check somewhere or something. If anyone can provide some help it would be greatly appreciated.
error message from debugger
error msg
which looks like makes the program crash on this line:
if (node->children_[index] == nullptr) {
search function
Node* search(const string& word, Node* node, int index) const {
Node* temp;
//same as recurssive lookup just difference is returns node weather terminal or not
if (index < word.length()) {
index = node->getIndex(word[index]);
if (node->children_[index] == nullptr) {
return nullptr;
}
else {
temp = search(word, node->children_[index], index++);
}
}
return temp; // this would give you ending node of partialWord
}
Node struct for reference
struct Node {
bool isTerminal_;
char ch_;
Node* children_[26];
Node(char c = '\0') {
isTerminal_ = false;
ch_ = c;
for (int i = 0; i < 26; i++) {
children_[i] = nullptr;
}
}
//given lower case alphabetic charachters ch, returns
//the associated index 'a' --> 0, 'b' --> 1...'z' --> 25
int getIndex(char ch) {
return ch - 'a';
}
};
Node* root_;
int suggest(const string& partialWord, string suggestions[]) const {
Node* temp;
temp = search(partialWord, root_, 0);
int count = 0;
suggest(partialWord, temp, suggestions, count);
return count;
}
Might be a very simple thing. Without digging I am not sure about the rank of the -> operator versus the == operator. I would take a second and try putting parenthesis around the "node->children_[index] == nullptr" part like this:
(node->children_[index]) == nullptr
just to make sure that the logic runs like you seem to intend.
Dr t
I believe the root cause is that you're using index for two distinct purposes: as an index into the word you're looking for, and as an index into the node's children.
When you get to the recursion, index has changed meaning, and it's all downhill from there.
You're also passing index++ to the recursion, but the value of index++ is the value it had before the increment.
You should pass index + 1.
[An issue in a different program would be that the order of evaluation of function parameters is unspecified, and you should never both modify a variable and use it in the same parameter list. (I would go so far as to say that you should never modify anything in a parameter list, but many disagree.)
But you shouldn't use the same variable here at all, so...]
I would personally restructure the code a little, something like this:
Node* search(const string& word, Node* node, int index) const {
// Return immediately on failure.
if (index >= word.length())
{
return nullptr;
}
int child_index = node->getIndex(word[index]);
// The two interesting cases: we either have this child or we don't.
if (node->children_[child_index] == nullptr) {
return nullptr;
}
else {
return search(word, node->children_[child_index], index + 1);
}
}
(Side note: returning a pointer to a non-const internal Node from a const function is questionable.)

Linked list without struct

Can anyone help me with a singly linked list? I know how to do it with struct, but now i wanna know how to do it with only arrays and pointers without struct or nodes.Algorithms please thank you.
#include <iostream>
using namespace std;
const int size=5;
int data[size];
int *mem;
int add[size];
int top = -1;
void AddLast(int value)
{
if(top==-1)
{
top=data[value];
}
else
{
top++;
top=data[value];
}
}
void print()
{ cout << "Queue: ";
for(int i = 0; i != top; i = (i + 1) % size)
{
cout << data[i] << "->";
}
cout << endl;
}
int main()
{
AddLast(2);
print();
AddLast(3);
print();
AddLast(4);
print();
cin.get();
return 0;
}
I want to addlast, addfirst, and add sorted... is this the way?
You can't do it with only one array, you need at least two: One for the data and one for the links. If you don't want to use structures at all (though I don't really see the reason for it) you could have multiple data arrays.
The data array contains the actual data, it's nothing special with it. The link array contains indexes to the data array, where each index is a "next" pointer.
For example, lets say you want to have a linked list of integers, and you have three integers in the list (their values are irrelevant), lets call that data array d, then you have d[0], d[1] and d[2]. The first node in the list is d[1], followed by d[0] and last d[2]. Then you need a head variable, which tells which index is the head of the list, this head variable is initialized to 1 (and "points" to d[1]). Then we have the link array, lets call it l, since the head is "pointing" to 1 we fetch l[1] to get the next node, the contents of l[1] is 0 which tells us the next node is d[0]. To get the next node we check l[0] which gives us 2 for d[2]. The next link, l[2] could be -1 to mark the end of the list.
Of course, the data array(s) and the link array needs to be of the same size.
An array s of structs with members A, B, C, can be emulated by three arrays a, b and c, where e.g. a[i] represents s[i].A, and so forth. So that's your requirement of no structs. Then doing a linked list with arrays, i.e. with indices instead of pointers, is mere notation; the concepts are exactly the same. But you might look up the technique of using a free list, a list of available logical nodes; this allows you to free nodes as well as allocate them, in a simple way.
There is a (ugly) way to do a linked list with arrays.
Here is an example of how you might do something with arrays but I would never recommend even thinking about doing it.
template<class T>
typedef char[sizeof(T) + sizeof(uintptr_t)] listNode;
template<class T>
listNode<T>* getNext(const listNode<T>& x){
return (listNode<T>*)(((char*)x)[sizeof(T)]); //notice how you have to increment the pointer address
}
template<class T>
T& getValue(listNode<T>& x){
return (T) x;
}
That's way too many casts. It's less ugly if you make an array of two pointers and just cast the first value in a pointer on what you care about but that's still not what I would recommend.
This is a hack of sorts might help with your curiosity.
It is similar in implementation to how linked lists are typically implemented with struct.
#include<stdio.h>
#include<stdlib.h>
int * base = NULL;
int ** current = NULL;
void add(int num)
{
if(base==NULL)
{
base = (int*)malloc(sizeof(int)*3);
base[0] = num;
current = (int**)(base+1);
current[0] = NULL;
}
else
{
current[0] = (int*)malloc( sizeof(int)*3 );
current[0][0] = num;
current = (int**)(*current+1);
current[0] = NULL;
}
}
void show()
{
if(base != NULL)
{
int * data = base;
int ** tmp = (int**)(base+1);
if(tmp[0]==NULL)
printf("%d\n",data[0]);
else
{
do
{
printf("%d ",data[0]);
data = tmp[0];
tmp = (int**)(data+1);
}while(tmp[0]!=NULL);
printf("%d\n",data[0]);
}
}
}
int main()
{
int choice,num;
do
{
scanf("%d",&choice);
switch(choice)
{
case 1:scanf("%d",&num);
add(num);
break;
case 2:show();
}
}while(1);
return 0;
}
It is possible to add other function like addFirst() or addSorted() but will require some more pointer manipulation, for which I don't possess the dedication right now.

Implementation of stack in C++ without using <stack>

I want to make an implementation of stack, I found a working model on the internet, unfortunately it is based on the idea that I know the size of the stack I want to implement right away. What I want to do is be able to add segments to my stack as they are needed, because potential maximum amount of the slots required goes into 10s of thousands and from my understanding making the size set in stone (when all of it is not needed most of the time) is a huge waste of memory and loss of the execution speed of the program. I also do not want to use any complex prewritten functions in my implementation (the functions provided by STL or different libraries such as vector etc.) as I want to understand all of them more by trying to make them myself/with brief help.
struct variabl {
char *given_name;
double value;
};
variabl* variables[50000];
int c = 0;
int end_of_stack = 0;
class Stack
{
private:
int top, length;
char *z;
int index_struc = 0;
public:
Stack(int = 0);
~Stack();
char pop();
void push();
};
Stack::Stack(int size) /*
This is where the problem begins, I want to be able to allocate the size
dynamically.
*/
{
top = -1;
length = size;
z = new char[length];
}
void Stack::push()
{
++top;
z[top] = variables[index_struc]->value;
index_struc++;
}
char Stack::pop()
{
end_of_stack = 0;
if (z == 0 || top == -1)
{
end_of_stack = 1;
return NULL;
}
char top_stack = z[top];
top--;
length--;
return top_stack;
}
Stack::~Stack()
{
delete[] z;
}
I had somewhat of a idea, and tried doing
Stack stackk
//whenever I want to put another thing into stack
stackk.push = new char;
but then I didnt completely understand how will it work for my purpose, I don't think it will be fully accessible with the pop method etc because it will be a set of separate arrays/variables right? I want the implementation to remain reasonably simple so I can understand it.
Change your push function to take a parameter, rather than needing to reference variables.
To handle pushes, start with an initial length of your array z (and change z to a better variable name). When you are pushing a new value, check if the new value will mean that the size of your array is too small (by comparing length and top). If it will exceed the current size, allocate a bigger array and copy the values from z to the new array, free up z, and make z point to the new array.
Here you have a simple implementation without the need of reallocating arrays. It uses the auxiliary class Node, that holds a value, and a pointer to another Node (that is set to NULL to indicate the end of the stack).
main() tests the stack by reading commands of the form
p c: push c to the stack
g: print top of stack and pop
#include <cstdlib>
#include <iostream>
using namespace std;
class Node {
private:
char c;
Node *next;
public:
Node(char cc, Node *nnext){
c = cc;
next = nnext;
}
char getChar(){
return c;
}
Node *getNext(){
return next;
}
~Node(){}
};
class Stack {
private:
Node *start;
public:
Stack(){
start = NULL;
}
void push(char c){
start = new Node(c, start);
}
char pop(){
if(start == NULL){
//Handle error
cerr << "pop on empty stack" << endl;
exit(1);
}
else {
char r = (*start).getChar();
Node* newstart = (*start).getNext();
delete start;
start = newstart;
return r;
}
}
bool empty(){
return start == NULL;
}
};
int main(){
char c, k;
Stack st;
while(cin>>c){
switch(c){
case 'p':
cin >> k;
st.push(k);
break;
case 'g':
cout << st.pop()<<endl;
break;
}
}
return 0;
}

Exponential tree implementation

I was trying to implement exponential tree from documentation, but here is one place in the code which is not clear for me how to implement it:
#include<iostream>
using namespace std;
struct node
{
int level;
int count;
node **child;
int data[];
};
int binary_search(node *ptr,int element)
{
if(element>ptr->data[ptr->count-1]) return ptr->count;
int start=0;
int end=ptr->count-1;
int mid=start+(end-start)/2;
while(start<end)
{
if(element>ptr->data[mid]) { start=mid+1;}
else
{
end=mid;
}
mid=start+(end-start)/2;
}
return mid;
}
void insert(node *root,int element)
{
node *ptr=root,*parent=NULL;
int i=0;
while(ptr!=NULL)
{
int level=ptr->level,count=ptr->count;
i=binary_search(ptr,element);
if(count<level){
for(int j=count;j<=i-1;j--)
ptr->data[j]=ptr->data[j-1];
}
ptr->data[i]=element;
ptr->count=count+1;
return ;
}
parent=ptr,ptr=ptr->child[i];
//Create a new Exponential Node at ith child of parent and
//insert element in that
return ;
}
int main()
{
return 0;
}
Here is a link for the paper I'm referring to:
http://www.ijcaonline.org/volume24/number3/pxc3873876.pdf
This place is in comment, how can I create a new exponential node at level i? Like this?
parent->child[i]=new node;
insert(parent,element);
The presence of the empty array at the end of the structure indicates this is C style code rather than C++ (it's a C Hack for flexible arrays). I'll continue with C style code as idiomatic C++ code would prefer use of standard containers for the child and data members.
Some notes and comments on the following code:
There were a number of issues with the pseudo-code in the linked paper to a point where it is better to ignore it and develop the code from scratch. The indentation levels are unclear where loops end, all the loop indexes are not correct, the check for finding an insertion point is incorrect, etc....
I didn't include any code for deleting the allocated memory so the code will leak as is.
Zero-sized arrays may not be supported by all compilers (I believe it is a C99 feature). For example VS2010 gives me warning C4200 saying it will not generate the default copy/assignment methods.
I added the createNode() function which gives the answer to your original question of how to allocate a node at a given level.
A very basic test was added and appears to work but more thorough tests are needed before I would be comfortable with the code.
Besides the incorrect pseudo-code the paper has a number of other errors or at least questionable content. For example, concerning Figure 2 it says "which clearly depicts that the slope of graph is linear" where as the graph is clearly not linear. Even if the author meant "approaching linear" it is at least stretching the truth. I would also be interested in the set of integers they used for testing which doesn't appear to be mentioned at all. I assumed they used a random set but I would like to see at least several sets of random numbers used as well as several predefined sets such as an already sorted or inversely sorted set.
.
int binary_search(node *ptr, int element)
{
if (ptr->count == 0) return 0;
if (element > ptr->data[ptr->count-1]) return ptr->count;
int start = 0;
int end = ptr->count - 1;
int mid = start + (end - start)/2;
while (start < end)
{
if (element > ptr->data[mid])
start = mid + 1;
else
end = mid;
mid = start + (end - start)/2;
}
return mid;
}
node* createNode (const int level)
{
if (level <= 0) return NULL;
/* Allocate node with 2**(level-1) integers */
node* pNewNode = (node *) malloc(sizeof(node) + sizeof(int)*(1 << (level - 1)));
memset(pNewNode->data, 0, sizeof(int) * (1 << (level - 1 )));
/* Allocate 2**level child node pointers */
pNewNode->child = (node **) malloc(sizeof(node *)* (1 << level));
memset(pNewNode->child, 0, sizeof(int) * (1 << level));
pNewNode->count = 0;
pNewNode->level = level;
return pNewNode;
}
void insert(node *root, int element)
{
node *ptr = root;
node *parent = NULL;
int i = 0;
while (ptr != NULL)
{
int level = ptr->level;
int count = ptr->count;
i = binary_search(ptr, element);
if (count < (1 << (level-1)))
{
for(int j = count; j >= i+1; --j)
ptr->data[j] = ptr->data[j-1];
ptr->data[i] = element;
++ptr->count;
return;
}
parent = ptr;
ptr = ptr->child[i];
}
parent->child[i] = createNode(parent->level + 1);
insert(parent->child[i], element);
}
void InOrderTrace(node *root)
{
if (root == NULL) return;
for (int i = 0; i < root->count; ++i)
{
if (root->child[i]) InOrderTrace(root->child[i]);
printf ("%d\n", root->data[i]);
}
if (root->child[root->count]) InOrderTrace(root->child[root->count]);
}
void testdata (void)
{
node* pRoot = createNode(1);
for (int i = 0; i < 10000; ++i)
{
insert(pRoot, rand());
}
InOrderTrace(pRoot);
}