I'm creating a small AVL tree class in C++, and I'm getting a bit mixed up with pointers here, and its acting rather strangely.
In the class, I have a variable named "root", which is a pointer to a node. At one point, I pass a pointer of this object into the following function:
template <class T> void AVL<T>::RRotate(Node ** node) {
std::cout << this->root << std::endl << *node << std::endl;
*node = (*node)->left;
std::cout << this->root << std::endl << *node;
}
(Note that 'left' is a field that contains a pointer to a node).
Now, the first print is always printing out the same memory location.
However, the second call will print a different directory for this->root and *node.
Why is this? When I set "*node = (*node)->left;", shouldn't it be changing this->root too, since node is just a pointer to that pointer?
I'm a tad confused.
Any help is appreciated!
EDIT: A sample output is as follows:
0x902a88
0x902a88
0x902a88
0x902aa8
EDIT 2: Printing out &this->root and node instead reveals that they're always the same value, so it looks like the pointer is pointing to the right place.
You should call RRotate(&root) if you want node to be a pointer to this->root.
Or, more detailed:
node = &(this->root);
this->RRotate(node);
Most likely, in your code node just doesn't point to the root field. Try printing node and &root.
Related
This problem seems like a trivial one but I am unable to get my head around it.
I am trying to add a node by passing in a root element to a function insert. The function first checks if the current root is empty, if it is, it simply creates a new node and set it as a root. My first attempt was something like this
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node(int x) {
data = x;
}
};
void insert(Node *node, int x) {
cout << &node << "\n";
if(node == NULL) {
node = new Node(x);
}
}
int main () {
Node *aNode;
aNode = NULL;
insert(aNode, 8);
cout << aNode << "\n";
return 0;
}
This of course didn't work since I was passing pointers by value which was causing aNode to be still NULL and with some googling I came to know I need to pass pointers by reference, my second attempt was something like this
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node(int x) {
data = x;
}
};
void insert(Node **node, int x) {
if(*node == NULL) {
*node = new Node(x);
cout << *node->data << "\n"; //gives error but program runs fine without it
}
}
int main () {
Node *aNode;
aNode = NULL;
insert(&aNode, 8);
cout << aNode->data << "\n";
return 0;
}
Now that worked without the cout in insert function since the cout in main printed 8 which is what I wanted but compiler gave error request for member 'data' in '* node', which is of pointer type 'Node*' (maybe you meant to use '->' ?) while at cout of insert. I changed the insert as follows to run some tests and results were confusing
void insert(Node **node, int x) {
if(*node == NULL) {
Node *bNode = new Node(x);
cout << bNode << "\n"; // prints address of bNode
cout << *node << "\n"; // prints NULL which is correct
*node = bNode;
cout << *node << "\n"; // prints the same address as of bNode
cout << bNode->data << "\n"; // prints 8
cout << *node->data << "\n"; // gives error WTF!!!
}
}
Can somebody please explain?
#RemyLebeau comment was spot on and pointed out the exact problem. So here is the solution.
Problem Background
So I had a pointer to an object of type Node aNode and had a function insert(Node *node, int x). I wanted the function insert to check if given pointer to node doesn't point to anything then create a new node and set the reference in provided node. The expectation was that after setting the reference aNode will point to the newly created node as well. However it was a false expectation because I was passing the pointer by value instead of reference which meant node in the function insert was a different one than aNode
Buggy Solution
So the solution was to pass reference of aNode to function insert. So I changed my function call to insert, to this
insert(&aNode, 8);
And change the function definition of insert to this
void insert(Node **node, int x)
That fixed the problem, since **node was now dereferened to the address of aNode and I was able to get its value by simply dereferencing node by *node. The problem occured when I tried to access members of Node by *node->data. The reason was that * and -> are actually operators and -> has higher precedence than *. So while evaluating *node->data it was actually executing in this way *(node->data) which means compiler was actually trying to dereference node->data instead of node. The quick solution was just to access data like this (*node)->data.
Right Solution
Although through parenthesis I was able to achieve the desired behavior but the syntax was ugly. The right solution as #pm100 pointed to use reference in function definition instead of dereferencing it twice which means declare function like this
void insert(Node *&node, int x)
instead of like this
void insert(Node **node, int x)
That enabled to access node members simply like node->data instead of (*node)->data
If you are new to pointers like me do watch https://www.youtube.com/watch?v=Rxvv9krECNw
I am currently reading a book on data structures and learning c++ on the side. I am trying to implement a simple linked list. Below is some code for a list that can take a maximum of two elements (in order to isolate my problem).
What is going wrong is the pointer declaration to the next node in the list. When I create a new Node instance and create a pointer to it, the pointer stays the same on each method call, so all elements in the list point to the same node. However, if I create a pointer directly, everything works as expected.
What I am guessing is that I have some fundamental misunderstanding of pointers, references and the new keyword.
Feel free to run the code below. The working code is commented out.
#include <iostream>
using namespace std;
template <typename T> class Node {
public:
Node(T nvalue) {
this->value = nvalue;
this->next = NULL;
}
T value;
Node *next;
};
template <typename T> class LinkedList {
public:
Node<T> *head;
LinkedList() {
this->head = NULL;
}
void append(T newVal) {
// Correct
// Node<T>* newNode_ptr = new Node<T>(newVal); // newNode_ptr is different on each call
// Incorrect!?
Node<T> newNode = Node<T>(newVal);
Node<T> * newNode_ptr = &newNode; // newNode_ptr is the same on each call
cout << "New Node Address: " << newNode_ptr << endl;
if (!(this->head)) {
this->head = newNode_ptr;
cout << "Value 0: " << this->head->value << endl;
} else {
this->head->next = newNode_ptr;
cout << "Value 0: " << this->head->value << endl;
cout << "Value 1: " << this->head->next->value << endl;
}
}
};
int main() {
LinkedList<int> list = LinkedList<int>();
list.append(21);
cout << "..." << endl;
list.append(42);
}
Note that this code is not exactly well designed (some stuff should be private, using namespace std should be avoided). I am familiar with python so this pointer stuff is a little overwhelming. Thanks for your help in advance!
Node<T>* newNode_ptr = new Node<T>(newVal);
This is the more correct way of the two. It is normal that the address of newNde_ptr is different, it's what you want. Each node is a different node, two different objects cannot have the same address! The version without new gives the same address because you are creating the objects on the stack. This will not work, every node is destroyed at the end of the append function. You will see unusual results (if it doesn't crash) if you move the printing portion of append to another function. Since all your pointers point to the same address (in your case) and at the point where you print out the values that address just so happens to be a valid Node, you do not see a crash. However, this is undefined behavior and can change for any number of reasons.
The difference between free-store (heap for malloc/free) and the stack is a fundamental concept of c++. You should read about it here.
The reason I saw more correct way of the two is that you still have to remember to delete your nodes. A better way would be to use std::unique_ptr instead of raw pointers to avoid that (and may other) mistakes that using raw pointers encourages.
// Node * next; becomes
std::unique_ptr<Node> next;
// Node<T> newNode = Node<T>(newVal); becomes
newNode = std::make_unique<T>(newVal);
I have found this code on the internet and I need a little help with it.
Here's the code:
#include<iostream>
using namespace std;
/* Linked list structure */
struct list {
struct list *prev;
int data;
struct list *next;
} *node = NULL, *first = NULL, *last = NULL, *node1 = NULL, *node2 = NULL;
class linkedlist {
public:
/* Function for create/insert node at the beginning of Linked list */
void insert_beginning() {
list *addBeg = new list;
cout << "Enter value for the node:" << endl;
cin >> addBeg->data;
if(first == NULL) {
addBeg->prev = NULL;
addBeg->next = NULL;
first = addBeg;
last = addBeg;
cout << "Linked list Created!" << endl;
}
else {
addBeg->prev = NULL;
first->prev = addBeg;
addBeg->next = first;
first = addBeg;
cout << "Data Inserted at the beginning of the Linked list!" << endl;
}
}
What I don't understand is when he is making the new Node object (in this case it's addBeg) he is putting a pointer operator in front of it. And how I'm seeing it now, shouldn't the object be created without the '*' before it's name and with the data, pointer to next and pointer to the previous one, unlike the pointer to the node in the list which should only contain address of the node, without any other data ? If that's not the case, then what is the thing that differs the pointer to the node in the list from the node itself ?
The way it's been done in the code is correct. You are having an incorrect understanding in that the data of a node cannot be accessed through the pointer to that node.
If addBeg is the pointer pointing to the node returned by new list, then the data of that node can be accessed using the operator ->:
list.data is equivalent to addBeg->data.
If that's not the case, then what is the thing that differs the pointer to the node in the list from the node itself ?
=> addBeg is the pointer pointing to an object, that object being returned by new List.
You didn't interpret this C++ declaration correctly... the meaning of code
list *addBeg = new list;
is
list* addBeg;
addBeg = new list;
list* in other words is the type of addBeg.
Note that the rules are indeed strange, because while the * being logically attached to first list to form the type, the meaning of
list *a, b;
will declare a to be a "pointer to list" and b to be a "instance of list" instead (so the meaning is attached to list but the star itself is attached to a).
Some programmers go quite far about this and:
They always put the star attached to the type (on the left)
They never declare two variables in the same construct
In my experience after writing enough code this interpretation problem will however disappear and even crazy syntax rule for C/C++ declarations will be reasonable easy to read (at least in simple cases).
I have TWO implementations of this.
Why does this particular implementation NOT work? I have a pointer to a pointer and im changing the inside point but it doesn't retain the change in the main function
#include <iostream>
using namespace std;
struct Node {
int value = 4;
Node* next;
};
void insertFront(Node*, Node**);
int main(){
Node head;
head.value = 32;
head.next = nullptr;
Node** headptr = new Node*;
(*headptr) = new Node;
*(*headptr) = head;
(*headptr)->value = 32;//redundant, I know
(*headptr)->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, headptr);
cout << head.value << endl;
system("pause");
return 0;
}
void insertFront(Node* newHead, Node** head2){
cout << "Inside before swap " << (*head2)->value << endl;
newHead->next = *head2;
*head2 = newHead;
cout << "Inside after swap " << (*head2)->value << endl;
}
Why does this one work? Can someone please explain IN DETAIL the pointer magic going on? I have a vague idea but im still a little bit confused. I understand that using a pointer to the head pointer allows you to change the head address globally but it's still a little bit cloudy. Can someone please clarify, what is going on with these pointers in both implementation?
#include <iostream>
using namespace std;
struct Node {
int value = 4;
Node* next;
};
void insertFront(Node*, Node**);
int main(){
Node** head = new Node*;
(*head) = new Node;
(*head)->value = 32;
(*head)->next = nullptr;
cout << (*head)->value << endl;
insertFront(new Node, head);
cout << (*head)->value << endl;
system("pause");
return 0;
}
void insertFront(Node* newHead, Node** head2){
cout << "Inside before swap " << (*head2)->value << endl;
newHead->next = *head2;
*head2 = newHead;
cout << "Inside after swap " << (*head2)->value << endl;
}
Both implementations are using double-indirection wrong, and both leak memory. You're question seems more about double-indirection than just about what works and what doesn't (whether you realize it or not). Its a C question, and though also applicable in C++, it is less so with that language because reference parameters make this somewhat easier (arguably).
I could simply say "use references to pointers" (which you could do), but that would be like you saying "why doesn't my car work?" and me answering "because this car over here will work". So I will provide a C answer (much to the dismay of my own common sense, as I can feel the furnaces firing up from the flamethrowers about to be sent my way). If I have time, I will include the C++ answer (using references), but no guarantees on that.
Pointers to pointers are no different than any other pointer type. All pointer types are types who's variables are defined to "point" to something of that type (I know, its repetitive and trivial, but bear with me here). The trivial example:
void foo(int x)
{
x = 5;
}
obviously doesn't change x on the caller side, and you seem keenly aware of that. If you want to change an in/out parameter using pointers, you need to declare the formal parameter to be a pointer-to type, dereference said-pointer parameter within the function body, and pass the address from the caller. Ie.
void foo(int *p)
{
*p = 5;
}
int main()
{
int x = 0;
foo(&x);
}
The truth is parameters are all pass-by-value in C, even pointer parameters. Yeah, read that again. You say what? Seriously. Its true. It just so happens the "value" you're passing is an address rather than the value within some variable, and in so being as such, the receiver must be something that is prepared to take, and manipulate, data via that address: a pointer.
Now. Pointers to pointers are no different. Pointers to pointers hold addresses of (wait for it...) pointers. Just like our first example, this:
struct Node
{
int data;
struct Node *next;
}
vod foo(Node* ptr)
{
Node *p = new Node();
p->data = 0;
p->next = ptr;
ptr = p;
}
int main()
{
Node *root = nullptr;
foo(root);
}
won't work. You can fix this several ways. One way is using a pointer-to-pointer (the C way). Another uses a reference to pointer (the C++ way).
First the C way, which demonstrates the whole mantra of passing something by address means declaring the parameter to be a pointer-to type (in this case a pointer to pointer type), and passing the address of the thing to modify:
void foo(Node** ptr)
{
Node *p = new Node();
p->data = 0;
p->next = *ptr;
ptr = p;
}
int main()
{
Node *root = nullptr;
foo(&root); // LOOK: passing address of our root pointer
}
Do you see how, just like in our trivial example using int and int*, we have to pass the address of the thing we're modifying to a function that takes a pointer-to-type? In this case the "type" is, itself, a pointer type.
Now, arguable, the C++ way using a reference is trivial by comparison, but IMHO it isn't as clear what is going on, only because there is literally a single character difference between the version that doesn't work and the version that does. Look at this:
vod foo(Node*& ptr) // LOOK added &
{
Node *p = new Node();
p->data = 0;
p->next = ptr;
ptr = p;
}
int main()
{
Node *root = nullptr;
foo(root);
}
Notice how everything else in this is identical to the version that does not work. Everyone has their preferences, and knowing what to look for allows me to use either method, but I can see why some have such difficulty writing and debugging what is essentially double-indirection code hidden in a reference type. Some engineers prefer to send all their out-params as pointer-to types, and I'm generally one of them.
Peeling Back Your Code
After all of that, lets peel back your code and see where things go to hell. I'll dissect the one that does not work, and hopefully you can see why neither version is honestly very good:
First your type:
struct Node
{
int value = 4;
Node* next;
};
Nothing horridly questionable here. The default value assignment in the structure definition. This will puke on non-current-day C++, so likely throw that out for now. If you want a default value, make a constructor (which you should have anyway to ensure all members are properly initialized to something):
struct Node
{
int value;
Node* next;
Node(int val = 4)
: value(val)
, next()
{}
};
Ok. Next up..
void insertFront(Node*, Node**);
You seem to want to use a pure node interface. Most people writing a linked list would do this:
void insertFront(Node** ppRoot, int value);
but we'll go with your version for now. The actual implementation of this:
void insertFront(Node* newHead, Node** head2)
{
newHead->next = *head2;
*head2 = newHead;
}
is correct. Yes it could orphan anything previously being pointed to by newHead->next, but that doesn't seem to be a concern of yours, so we go with it for now.
Finally the torrent: main().
int main()
{
Node head;
head.value = 32;
head.next = nullptr;
Node** headptr = new Node*;
(*headptr) = new Node;
*(*headptr) = head;
(*headptr)->value = 32;//redundant, I know
(*headptr)->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, headptr);
cout << head.value << endl;
system("pause");
return 0;
}
This has multiple issues. First, your mixing dynamic nodes with non-dynamic nodes.
Node head;
head.value = 32;
head.next = nullptr;
Bad idea. This is no reasonable way calling code (in particular cleanup code that deletes each node from the list), has any clue whether something being pointed to is dynamic or not. Don't do that.. Using the constructor version of Node from above, this should simply be:
Node* head = new Node(32);
Next you're dynamically allocating a pointer; (not a Node; a pointer)
Node** headptr = new Node*;
Bad idea. there is no need to do that at all. You already have a pointer variable to your list head (its called, not-coincidentally, head). This appears all to be a setup for invoking the insertion function. To do that, everything from Node** headptr = new Node*; on down can simply be replaced with this:
insertFront(new Node(10), &head); // LOOK: passing address of head pointer
cout << head->value << endl;
The way you are using your pointers is so, so wrong.
Let's look at this code:
Node** headptr = new Node*;
(*headptr) = new Node;
*(*headptr) = head;
(*headptr)->value = 32;//redundant, I know
(*headptr)->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, headptr);
cout << head.value << endl;
Let's first clean up this code a bit. There is no reason to allocate a Node * on the free store (using new), and then reference it through a Node **. It can and should simply be a local variable and referenced directly. To do that, we replace Node** headptr = new Node*; with simply Node *phead, and replace all instances of (*headptr) with merely phead:
Node* phead;
phead= new Node; // #2
*phead= head; // #3
phead->value = 32;//redundant, I know
phead->next = nullptr;//redundant, I know
cout << head.value << endl;
insertFront(new Node, &phead); // here we are passing the address of phead so that insertFront() can modify it
cout << head.value << endl;
Now look at this code carefully. You allocated space for a new Node on line 2, and made phead point to it. You copied the contents of head into this new Node on line 3. Then your insertFront() call modified a newly allocated node and set phead to point to that new node instead. At no point did any pointer ever point to head, and its value is never touched; when you check head.value, of course they remain the same.
I have a problem with this very simple block of code. please give me your advice .
(My this problem is solved, and in solving this problem the person having id stakx really helped me, the only problem was that i was using stack< treeNode >, when i saw the push method of the stack carefully, there is a copying process when i write head->object=number, so finally i made the stack of pointers, like this stack< treeNode* > and it really solved the problem , i have no problem now , i am very very thankful to the person stakx.)
before the code you need to suppse the following tree
alt text http://img44.imageshack.us/img44/7016/avlimage06.jpg
as you can see in the picture that root is 8 and stack have two nodes i.e 6 and 4. i pass this stack and root node to the following code
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
{
if(!s.isempty())
{
treeNode *stacknode;
stacknode=s.pop();
cout<<"\ninside the attachwithtree function, stack node is "<<stacknode->data;
stacknode->right=tree;//attaching the passed node to the right of popped node
root=stacknode;//setting the root to stack node which is the private data member of class
updatebalance(root);//this function is ok, it does not create problem
while(!s.isempty())
{
cout<<"\nstack is still not empty";
stacknode=s.pop();
cout<<"\nright side of "<<root->data<<" is "<<(root->right)->data;
//the below three lines causing the problem i don't know why,
root=stacknode;
treeNode* temp;
temp=root->right;
cout<<"\n\n\nthe right side of "<<temp->data<<" is now "<<(temp->right)->data;
updatebalance(root);
}
the ouptput of this function is given by
here is the code of the pop method of the stack that i am using
template <class t>
t * Stack<t>::pop()
{
if(topelement!=NULL)
{
t* num;
current=topelement;
num=&(current->object);
topelement=topelement->preptr;
current=topelement;
return(num);
}
else
{
head=NULL;
}
}
here is the code of push method of the stack
template <class t>
void Stack<t>::push(t &number)
{
Node<t>* newNode=new Node<t>;
if(head==NULL)
{
head=newNode;
topelement=newNode;
current=newNode;
head->object=number;
head->preptr=NULL;
}
else
{
topelement=newNode;
newNode->preptr=current;
current=topelement;
newNode->object=number;
}
}
Original answer:
Could it be that the node 4 on the stack has a different node 6 to its right (the one with node 7 to its right) than the node 6 (with the node 8 on its right) you're working on? You could compare their addresses to make sure you haven't got two different copies of node 6 around.
Elaboration on the above argument:
Let's look at your method's signature:
void Avltree::attachwithtree(treeNode* tree, Stack<treeNode>&s)
s is defined as a reference to a Stack<treeNode>.
Could it be that it should be a Stack<treeNode*>?
Depending on your treeNode class, it's possible that when you push X on this stack, you actually end up with a copy of X and not X itself. Similarly, when you pop from the stack, you might not actually get the item you pushed, but an identical-looking copy of it!?
This would mean that, at the time when you push node 6 on the stack, its right child is node 7. But you have pushed a new, identical node on the stack. Even if you pop this element from the stack and change it, you only change a copy and leave the original tree node as it was before.
Therefore, you'd operate on different copies of node 6. First, you pop a copy of it from the stack, and append a tree as its right child. Checking this will give the right result.
Then, you pop a copy of node 4 from the stack. It's right child is node 6, as expected, BUT not the one you just modified but the original! Therefore you get 7 on the right side of node 6.
Demonstrating the difference between pass-by-value and pass-by-reference:
OK, here's something you need to understand when working with pointers or references. It basically shows the difference between passing a parameter by value (a copy will be created) or passing it by reference (no copy will be created).
Study it carefully and then see how it applies to your problem.
#include <iostream>
class someObject
{
private:
int _value;
public:
someObject(int value) : _value(value) { }
int getValue()
{
return _value;
}
};
void someFunction(someObject objCopy, someObject* objPtr)
{
std::cout << "objCopy.getValue() -> " << objCopy.getValue() << std::endl;
std::cout << "objPtr->getValue() -> " << objPtr->getValue() << std::endl;
if ( &objCopy != objPtr )
{
std::cout << "objCopy is not actually *objPtr but a copy of it." << std::endl;
}
else
{
std::cout << "objCopy and *objPtr are one and the same object." << std::endl;
}
}
int main()
{
someObject X(17);
someFunction(X, &X);
return 0;
}
Hint: Yes, in your pop method, you work with pointers, but most likely with a pointer to a copy of the object originally pushed on the stack.
Is that your own Stack class? A quick look at the STL tells me that pop() has return type void.
It could be that stakx is onto something here. If your pop() function returns a copy of the top element rather than a reference to it, the changes you make will only apply to the copy. Do you explicitly add the copy back into the tree anywhere after modifying it?