Why does this binary search tree cause a stack overflow? - c++

#include<iostream>
using namespace std;
/*main idea is to construct ordered statistic tree,which is similar of
binary search tree,width addition of one key,which shows us it's rank in given
tree,for this i introduced additional one key-rank
*/
struct node
{
int val;
node *left,*right;
int rank;
node(int t) { val=t;left=right=NULL;}
};
node *root;
void insert(node *p,int ele)
{
if(p==NULL){
p=new node(ele);
return ;
}
else if(ele<p->val)
{
insert(p->left,ele);
}
else if(ele>p->val)
{
insert(p->right,ele);
}
}
void inorder (node *p)
{
if(p!=NULL){ inorder(p->left);
cout<<p->val<<" "<<p->rank;
inorder(p->right);
}
}
int count_node(node *t)
{
int sum=0;
if(t==NULL) return 0;
else sum=1;
if(t->left) sum+=count_node(t->left);
if(t->right) sum+=count_node(t->right);
return sum;
}
int main()
{
root=NULL;
root->rank=0;
insert(root,26);
insert(root,17);
insert(root,41);
insert(root,14);
insert(root,30);
insert(root,21);
insert(root,47);
insert(root,10);
insert(root,16);
insert(root,28);
insert(root,38);
insert(root,35);
insert(root,39);
insert(root,19);
insert(root,21);
insert(root,20);
insert(root,7);
insert(root,12);
insert(root,3);
inorder(root);
return 0;
}
This code causes an overflow, but I do not understand why, because I have constructed the constructor properly.

The problem is:
root=NULL;
root->rank=0;
this cause undefined behavior because you dereference a NULL pointer. Anything can happen.
Also:
void insert(node *p,int ele)
{
if(p==NULL){
p=new node(ele);
return ;
}
//...
}
This doesn't modify the original pointer. If you call insert on a NULL pointer, it will be NULL when the function returns. You need to pass it by reference:
void insert(node *& p,int ele)

In addition to what Luchian said, you also have this problem:
void insert(node *p,int ele)
{
if(p==NULL){
p=new node(ele);
return ;
}
....
where the pointer p is passed by value. When you say p=... you are changing a copy of the pointer that is only visible to the function. You might want a reference to the pointer you're changing:
void insert(node *&p, int ele){ ... }

You have a very big issue the first two lines of your main function:
root=NULL;
root->rank=0;
If you look at your own definition above, the root is defined as a node pointer, that is it does not reserve any space for an actual node.
If you do not reserve the space yourself, than you are trying to write through uninitialized memory. What's more, you explicitly say that the root points to nothing, that is NULL. And in the very next line, you try to access it's member called rank.
You should try replacing the line:
root = NULL;
With
root = new node(0);
or something similar that actually reserves the space and constructs a node.
Alternatively, you could try assinging the rank to the root in the very end, since you insert function actually constructs the root if it is not present. edit as Luchian said, you only try to construct the root in the insert method. If you re-write the insert method in the way he has suggested, than it might all work if you just move the root->rank=0; line to the end of the insertion process.

root=NULL;
root->rank=0;
This could be the problem, you should not deference a NULL object.

Related

Displaying elements of a Generic Tree

I am trying to display all elements of this Generic Tree, in the fashion -
NodeData --> (list of all the children data)
According to the input given, my output should be-
10-->5,6
5-->4,1
6-->
4-->
1-->
I am unable to figure out what is going wrong, my o/p is only 10--> for some reason.
I've written a recursive code for printing the generic tree. Please help me out..
My code is :
using namespace std;
class Node
{
public:
int data;
vector<Node> children;
};
void printTree(Node *node)
{
cout<<node->data<<"-->";
for(auto x:node->children)
cout<<x.data<<",";
cout<<endl;
for(auto x:node->children)
printTree(&x);
}
int main()
{
int a[]={10,5,4,-1,1,-1,-1,6,-1};
int n=sizeof(a)/sizeof(a[0]);
stack<Node> s;
Node root;
for(int i=0;i<n;i++)
{
if(a[i]==-1)
s.pop();
else
{
Node temp;
temp.data=a[i];
if(s.size()==0)
{
root=temp;
}
else
{
s.top().children.push_back(temp);
}
s.push(temp);
}
}
printTree(&root);
return 0;
}````
To print your tree you need to have a pointer to the top of the tree which is what root is meant to be. To fix root so that it can reference the top of the top tree, make root to a pointer type (Node *). Then when you set root = &temp, root will point to the top of your tree rather than just a copy of the top node.
Your code declares root as an un-instantiated object. As such, root = temp triggers a shallow copy of temp into root at the time of execution. After the copy is done, changes to temp are not reflected in root because they are distinctly separate objects. Although it should be noted that if the objects were to have pointer type properties, then the pointers would be copied and thus both object would have a separate pointer to the same memory space.

C++ Linked Lists and Pointers to Pointers

First post but I have been a lurker for some time now :)
First, I am attempting to execute this skeleton code in Visual Studio 2015 and it should work as is according to my teacher so I am not sure what else could be wrong client side that may be causing that.
Finally, the overall issue here is I am not sure how to complete the remain commands. I understand the basic concepts of how the pointer to pointers work as well as the linked lists but not completely. My first issue is not helping either.
Any help would be greatly appreciated.
Thanks,
Several
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int value;
struct _node *next;
} node;
void append(node**, int);
void prepend(node**, int);
void lprint(node*);
void destroy(node*);
int main(int argc, char **argv)
{
node *head = NULL;
append(&head, 1);
append(&head, 2);
append(&head, 3);
prepend(&head, 0);
prepend(&head, -1);
prepend(&head, -2);
lprint(head);
destroy(head);
return 0;
}
void append(node **head, int value)
{
if (*head == NULL)
{
*head = (node*)calloc(0, sizeof(node));
(**head).value = value;
}
else
{
node *temp;
for (temp = *head; (*temp).next != NULL; temp = temp->next);
(*temp).next = (node*)calloc(0, sizeof(node));
(*temp).(*next).value = value;
}
}
void prepend(node **head, int value)
{
}
void lprint(node *head)
{
node *temp;
for (temp = head; temp != NULL; temp = temp->next)
{
printf("%d ", temp->value);
}
printf("\n");
}
void destroy(node *head)
{
}
I was able to compile and run your code after changing this line:
(*temp).(*next).value = value;
to this:
(*temp).next->value = value;
When I ran it, it printed out:
1 2 3
... which is what I would expect, given that prepend() isn't implemented.
I could write an implementation of prepend() and post it here, but I don't want to risk doing your homework for you; instead I'll just describe how prepend() ought to work.
For the case where head is NULL, prepend() can do the exact same thing that append() does: allocate a node and set head to point to that node.
For the other case, where head is non-NULL (because the list is non-empty), it's pretty easy too -- even easier than the append() implementation. All you need to do is allocate the new node, set the new node's next pointer to point to the existing head node (*head), and then set the head pointer (*head) to point to the new node.
The destroy() function can work with a loop very similar to the one in your lprint() function, with one caveat -- you have to grab the next pointer out of a given node (and store it into a local variable) before you free() the node, because if you free the node first and then try to read the next-pointer from the already-freed node, you are reading already-freed memory which is a no-no (undefined behavior) and will cause bad things (tm) to happen.

Passing a pointer to a function

I was trying to implement BST using C++ , so i tried this:
#include <iostream>
#include <stdlib.h>
struct node
{
int value;
node* left;
node* right;
};
void insert(node *cur , int val)
{
if(!cur)
{
cur = new node;
cur->value = val;
cur->left = NULL;
cur->right = NULL;
return;
}
if(val <= cur->value)
insert(cur->left , val);
else
insert(cur->right , val);
}
using namespace std;
int main()
{
node *root = NULL;
insert(root , 20);
insert(root , 21);
cout<<(*root).value;
return 0;
}
but I have a problem, my insert() function works good, but the change in cur does not seem to reflect into the root pointer, as root remains NULL after the `insert() function calls. What is wrong here?
EDIT: Thanks for all your answers, making a pointer to a pointer seems to be to be ugly and tedious, is there any other way around, acheiving this with some other design?
Here, the root itself has been passed to insert() using pass-by-value. so, from insert(), the value of root cannot be changed. In other words, the cur is local to insert() function. Any changes made to cur itself won't impact the actual argument passed.
If you want to change the value of root from insert(), you need to pass a pointer to root from main().
To elabotare, you can change the value at the address pointed by cur from insert(). So, following the same analogy, if you change
insert(&root , 20);
void insert(node **cur , int val)
all the occurrences of cur to *cur
you should be all good to go.
If you want the function to operate on the outside pointer rather than a local copy you need to pass by reference:
void insert(node*& cur, int val)
{
// ...
}
Otherwise the function works on a copy of the pointer and the outside variable remains unchanged.
The wrong is that you pas a pointer by value, change that value but the caller does not know about it. Change it to
void insert(node **cur , int val)
{
if(!*cur)
{
*cur = new node;
(*cur)->value = val;
(*cur)->left = NULL;
(*cur)->right = NULL;
return;
}
if(val <= (*cur)->value)
insert((*cur)->left , val);
else
insert((*cur)->right , val);
}
And change function call accordingly (...exercise!)
C++ makes function calls as Call by Value. So it makes a copy of the pointer and passes that to the function. If you pass that pointer, you have access to the data the pointer is pointing to, but NOT to the pointer outside the function itself, as only the adress the pointer is pointing to is copied.
You need to pass a pointer to the pointer if you want to modify the pointer itself (that would be the C attempt) or pass by reference, of which c++ is capable of.
If you want to use the C attempt:
void insert(node ** cur , int val)
if(!(*cur))
{
(*cur) = new node;
(*cur)->value = val;
(*cur)->left = NULL;
(*cur)->right = NULL;
return;
}
or the C++ attempt (here you only have to modify the type of cur, everthing else will remain as it is):
void insert(node *& cur , int val)
If you reassign cur to a new node in insert, that does not mean that root is assigned that value (especially that root is not an address at all, but NULL).
Either pass a pointer to an empty node to insert on initialization (and update it with relevant data) or return a new node (and assign it to root in main).

C++ pointer troubles

I am having trouble with the following code. I am a java developer trying to teach myself c++. Mainly my code in main() is not inserting anything to the root Node. Can anyone help me. I am sure there is something off with my pointers.
class Node{
public:
Node* left;
Node* right;
int data;
Node(int n){
data = n;
right = NULL;
left = NULL;
}
};
class BST{
Node* root;
public:
BST(){
root = NULL;
}
void insert(int e){
pinsert(root, e);
}
void pinsert(Node* sr, int e){
if(sr == NULL){
sr = new Node(e);
}
else{
if((sr->data) > e ){
pinsert(sr->left, e);
}
else{
pinsert(sr->right, e);
}
}
}
};
int main(){
BST tree;
tree.insert(6);
tree.insert(7);
}
You pass sr by value and assign to it. This won't change you root. Pass it by reference instead:
void pinsert( Node*& sr, int e)
The problem with your insert is when you begin with an empty list. When you pass a Node * to your pinsert function, the argument is passed by value, so your function ends up with a copy of the pointer. When the pointer is NULL, you change the pointer to point to your new node. Since you only have a copy of the pointer in pinsert, this only changes the copy of the pointer. When the function returns, the pointer, and the list, is unchanged.
Pass a reference to the pointer to get around this:
void pinsert(Node *&sr, int e)
Now the rest of your code doesn't need to change, and your function can change the pointer.
This problem is analogous to passing object references in java: you can change the contents of the object, by setting fields and calling methods, but you can't change the argument to a new object, or to null.
The problem is that root is always NULL, you never assign anything to it.
When you call pinsert(root, e) and then do this:
void pinsert(Node* sr, int e){
if(sr == NULL){
sr = new Node(e);
}
you send a copy of root and assign to that copy, not the root which remains NULL. You need to either send the pointer by reference (void pinsert(Node** sr, int e)) - notice 2 'stars' or void pinsert(Node*& sr, int e).

Bool function always true & Tail Node Removal in Singly-Linked List creates infinite loop

ok this is me training on singly-linked lists, being a newbie... However, somewhere I must be messing things up. My code is pretty straight forward containing all the typical procedures you would expect..
Problems:
My boolean function is always true even when I type in numbers that are not in the list
Here's my code, look at the main function as well to get an idea of the order in which things happen. Ooh and thank you for your help!! :)
#include <string>
#include <iostream>
using namespace std;
class Node
{
public:
int n;
Node* link;
};
void display(Node* head)
{
cout<<head->n<<" ";
while(head->link!=NULL)
{
head=head->link;
cout<<head->n<<" ";
}
cout<<endl;
}
void addnode(Node*& head, int x)
{
if(head==NULL)
{
head=new Node;
head->n=x;
head->link=NULL; // Necessary? Why?
}
else
{
Node* p=new Node;
p->n=x;
p->link=head;
head=p;
}
}
bool found(Node* head, int x)
{
if(head->n==x) return true;
while(head->link!=NULL)
{
head=head->link;
if(head->n==x) return true;
}
return false;
}
void addtail(Node*& head, int x)
{
if(head==NULL)
{
head=new Node;
head->n=x;
head->link=NULL;
}
else
{
Node* q=NULL;
q=head;
while(q->link!=NULL) q=q->link;
Node* r=new Node;
r->n=x;
r->link=NULL;
q->link=r;
}
}
int removehead(Node*& head)
{
if(head==NULL)
{
cout<<"The list is empty";
return 0;
}
int x;
if(head->link==NULL)
{
x=head->n;
head=NULL;
return x;%0stackoverflow.com
Node* p=NULL;
p=head;
head=head->link;
x=p->n;
delete p;
return x;
}
int removetail(Node*& head)
{
if(head==NULL)
{
cout<<"The list is empty";
return 0;
}
int x;
if(head->link==NULL)
{
x=head->n;
delete head;
Node* head=NULL;
return x;
}
Node* p=NULL;
p=head;
while(p->link!=NULL) p=p->link;
x=p->n;
delete p;
return x;
}
int main()
{
int y; int z;
Node* p=NULL;
while(cin>>y)
{
addnode(p,y);
}
cin.clear(); cin.ignore();
cout<<endl;
display(p);
cout<<endl;
cout<<removehead(p)<<" ";
cout<<removetail(p)<<endl;
display(p);
cout<<endl<<"give me a number:";
cin>>z;
if(found) cout<<endl<<"found";
else cout<<endl<<"not found";
}
.(when I remove the tail node, is the link of the previous one now just pointing at some random part of the memory? Is that the problem? And why the infinite loop?
Looks like it:
int removetail(Node*& head)
{
// base cases elided
Node* p=NULL;
p=head;
while(p->link!=NULL) p=p->link;
x=p->n;
delete p;
return x;
}
The previous link, that pointed to the p you are deleting, still points to p. Bad. It should be something like this:
int removetail(Node*& head)
{
// base cases elided
Node* p=NULL;
p=head;
while(p->link->link!=NULL) p=p->link;
x=p->link->n;
delete p->link;
p->link = NULL; // maintain linked list integrity
return x;
}
This is safe to do (assuming memory isn't corrupted for other reasons) because you've already checked if head==NULL and head->link == NULL in one of the base cases, so an initial call to p->link->link = head->link->link will not give you any improper pointer access. If head->link->link == NULL, that's ok.
And why the infinite loop?
An interesting question.
For a slightly flawed philosophical explanation: assuming you don't get an illegal memory access error caused by accessing a bad pointer, you're talking about a pointer value that randomly points somewhere. Real memory is finite, so any sequence of pointer references in a finite set have to repeat at some point in a cycle (otherwise the set would not be finite). Of course, that could include a NULL which would stop the infinite loop.
More likely you're hitting some bad memory pattern reserved by the OS memory manager, like 0xcdcdcdcd which points to 0xcdcdcdcd. In which case it is a bad choice: default memory patterns should probably be designed so that if they show up in a pointer, they are likely to cause a bad memory exception.
You could stop the program in a debugger and tell us what the pointer value is, and that would answer that part of the question.
You should turn on warnings when you compile. Here is what the compiler says:
% g++ -Wall list.cc
list.cc: In function ‘int removetail(Node*&)’:
list.cc:120:15: warning: unused variable ‘head’ [-Wunused-variable]
list.cc: In function ‘int main()’:
list.cc:166:13: warning: the address of ‘bool found(Node*, int)’ will always evaluate as ‘true’ [-Waddress]
The first error points out that you declared a local variable head in function removetail (with Node* head=NULL;), while you probably meant to update the argument's value (with just head=NULL;).
The second error explains why found (an address) is always true. You probably meant to call the function found(...) with some arguments.
The first thing is that you do
if(found) cout<<endl<<"found";
which should probably be
if(found(p,z)) cout<<endl<<"found";
The first version is basically checking if the function pointer to "found" is not null, ie that it has a value. The second actually calls the function as you probably wanted.
The second thing is that when you remove the tail. you're not actually removing it from the list, you're just deleting it. You need to unlink it from the list too or you'll point to uninitialized memory.