Problems dereferencing node defined by struct - c++

This is for a homework assignment, so explanations (and not direct code) are what I need.
We recently started learned about copy constructors/assignment = operators and such. In the handout we got in class our professor showed us how if you want to deep copy pointers you have to dereference them and copy the values directly.
Eg: (from handout)
class IntCellFixed {
public:
IntCellFixed(int initialValue = 0) { storedValue = new
int(initialValue); }
//v This bit here v
IntCellFixed(const IntCellFixed &source) {
storedValue = new int();
*storedValue = *source.storedValue;
}
//^ This bit here ^
(...)
private:
int *storedValue;
};
This makes sense to me. You have a pointer, and you want to have the value it points to be equal to the value of the pointer you're copying from. So you do * to have it change the value at the address it's pointing at, and not the address itself. That makes sense to me.
So when we went to apply that in lab, I tried a similar thing, but with linked lists instead of just pointers to an integer. Even with the TA's help (with the TA looking at and tweaking my code until it was the "correct" thing), it still did not work and just gave me a segfault. I did not have a chance to ask what exactly the code was supposed to be, and the solution hasn't been posted yet.
We're doing almost the same thing in our homework. Here is the structure of our node (in a binary search tree):
struct Node {
int data;
int count;
Node *left;
Node *right;
};
In my void BinarySearchTree::insert(Node *node,Node *parent, int value) function, I have this bit of code:
if (node == NULL) {
node = new Node();
*node->data = value;
*node->count = 1;
node->left = NULL;
node->right = NULL;
}
When I try to do this, however, it gives me the error: invalid type argument of unary ‘*’ (have ‘int’).
When I take off the *, it runs fine, but doesn't actually save the data for the node outside of the insert function. (ie: when trying to insert multiple values, it always starts with an empty tree, even after I've supposedly inserted values already).
As far as I understand it, I WOULD need to dereference the node because I don't want the address it's pointing to to change, I want what's AT the address to change.
Am I just completely misunderstanding how/when to dereference? If I am, could somebody explain when I would need to, and why I wouldn't need to in this case? Or, if it's a syntax error, could somebody tell me what the syntax should be?

Related

Trie Tree Initialization

I am using C++ to construct a trie tree with a bunch of words in dictionary. This is how I defined my TrieNode and built a tree:
struct TrieNode {
TrieNode *children[26];
bool isWord;
TrieNode(): isWord(false) {} /* to be deleted */
};
void buildTree(TrieNode *root, string word) {
TrieNode *cur = root;
for (char c : word) {
if (!cur->children[c-'a'])
cur->children[c-'a'] = new TrieNode();
cur = cur->children[c-'a'];
}
cur->isWord = true;
}
This works fine on some compilers, but on others this produces some strange results. For example, one time I found isWord was initialized to be 152, and the whole program crashed. I tried deleting the line marked above in the code, things worked out again. What is going on here?
Also, what is the difference between "new TrieNode()" and "new TrieNode"? Sometimes I found they produce different results too.
The problem with your code, is that you assume the members to be initialized. Unfortunately, this is not true. So the pointers to the children are not necessarily initialized to nullptr, which causes your code to dereference invalid pointers, which causes undefined behavior (UB) (e.g. memory corruption, crashes, etc...).
Easy solution:
Add a default initializer for your array in the class:
TrieNode *children[26]{};
Demo
My advices:
use vectors instead of native arrays. Their default constructor ensures they are empty.
read this article about initialisation
make some bound checking, because if some capitals are lost in your data, you'll go out of range, and again, UB.

Understanding linked list with C++?

I get the idea of linked list being some kind of way of navigating through some kind of array/list/vector of sorts. I don't think i have the full idea of the concept. I've seen some charts explaining them but I don't seem to understand how they work. So I thought actually looking at the code might help. (My professor doesn't really go over the code that much)
I copied this code from some video.
#include<iostream>
using namespace std;
struct node
{
int num;
node *link;
}*p; // i'm not sure how this pointer was declared
void main()
{
node *root;
root = new node;
root -> num = 5;
root -> link = p;
p = root;
node *q;
for (q = p; q != NULL; q = q -> link)
{
cout << q -> num << endl;
}
}
I guess I don't know what the -> operator does exactly. I know it has something to do with pointers and I'm not sure how that for loop is working.
If someone could take me through the code or if they may have a better example to show me and also if there is any more info that I should know please tell. It would be appreciated.
I think the code is slightly incorrect (or maybe just bad style since it relies on the fact that the pointer is NULL after initialization) as is but I will try to explain this in detail.
Firstly the -> operator evaluates to a dereference followed by a dot ., so root->num is equivalent to (*root).num.
A linked list (in your case a singly linked list) is a structure like follows
NODE{1} --> NODE{3} --> NULL
Here a node is a struct object and has a pointer to another object. These objects together constitute the linked list. As you can see you need some sort of pointer to point to the first element in the linked list. In the example above that element would be the node with the 1 stored in it. This is the root pointer that you have in your code above.
The new is an allocation. You need to place the objects of your linked list somewhere in memory and the new operator helps you find some place in memory (particularly somewhere on the heap) you can store your object. And then it returns a pointer to this location. The best way to learn more about the heap is to research this online. This is an introductory concept (with a lot of "upper level" concepts at the implementation level but you do not have to worry about that at the moment) that is explained very well online. This will likely be better than reading my explanation so I will not explain more about the heap and the stack here. However I think the following links should be helpful
http://www.cplusplus.com/doc/tutorial/dynamic/
http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html
http://www.tutorialspoint.com/cplusplus/cpp_dynamic_memory.htm
You also need to know where to stop in the linked list, i.e. you need to know which element is the last element. In the case above the last element is the node with the 3 in it. So this node will not point to another Node object but will rather point to NULL, 0 or the preferred nullptr in C++11 and C++14 (soon also C++17). So you could construct the linked list above with the following code.
#include <iostream>
using std::cout;
using std::endl;
struct Node {
int element;
Node* next;
};
int main() {
Node* root = new Node;
root->element = 1;
root->next = new Node;
root->next->element = 3;
root->next->next = NULL;
for (auto i = root; i != NULL; i = i->next) {
cout << i->element << endl;
}
return 0;
}
Does that make sense?

Member function returns the previous value of a variable

I am constructing an AVL tree program. I got stuck in a rather easy situation, but difficult to understand what is wrong. The reason I think it is the program's fault and not mine is because I have the exact same class function right before it with "left" and "right" swapped and it works just fine...
As you can see, the function returns the temproot pointer which is equal to temp2 if root==temp. The funny thing is, that although when I test-print the value of temproot JUST before it returns it (that in my example is 15), the actual value that is returned is STILL 20 (the previous value of temproot). I triple checked everything. It doesn't seem to return the newly acquired value... What may be the problem?
To be more specific, the exact code is this:
//structure
struct avlnode
{
int data;
avlnode * left;
avlnode * right;
}* root;
//class function
avlnode * Tree::RL_rotation (avlnode * temp)
{
avlnode * temproot = temp;
avlnode * temp1= new avlnode;
temp1=temp->right;
avlnode * temp2= new avlnode;
temp2=temp1->left;
temp1->left=temp2->right;
temp2->right=temp1;
temp->right=temp2;
temp->right=temp2->left;
temp2->left=temp;
if (root==temp)
{
root=temp2;
temproot=temp2;
}
cout << "temproot= " << temproot->data << endl;
return temproot;
}
I don't see a problem in the functionality you are seeing.
Pointers work in different ways than your typical objects (values), and are pretty hard to explain without having drawing board at hand, but let me try.
When you "remember" the pointer to initially passed in node, you are remembering just that. Even if you assign initial pointer to different structure fields, "move it around", your "copy" will still point at the exact same element, since the actual memory doesn't move when you are assigning/reassigning pointers. And, because of that (in your case), the rotation you are doing, won't be reflected by the parent element, of the initially passed in root, since it would still be pointing to the same element that got assigned to temp2->left (as is temproot, since the actual memory weren't reassigned).
If you want to change (have access to) the location where the actual element is stored. As I assume is within your case, you need to pass in the root element of the rotation by reference (avlnode* Tree::RL_rotation (avlnode*& temp)). And by doing that, you will pass, to the function, not only the memory location of your node, around which you want to do the rotation, but the location of the location as well. Which would allow to change the root, after the rotation, which you weren't able to do before.
Note: Get rid of code like this:
avlnode * temp1= new avlnode;
temp1=temp->right;
You are creating a new memory location, which you immediately forget, and it never gets released (there's no garbage collector in native C++).
Instead, write like this (since you don't really need to create new node - you are only rearranging them):
avlnode * temp1= temp->right;

Accessing Vector of Nodes

Just a quick C++ question. I've been trying to save a node inside a vector to the right child of a node.
For example,
I have a struct called node that has a pointer leading to a left child and a right child.
So:
struct node{
node *left;
node *right;
};
My vector of nodes,
vector<node> nodeVec;
consists of nodes as well.
The goal is to then take a node out of my vector and save as the right and left child of a new node.
So:
node *tree = new node();
tree->left = *nodeVec.at(0);
tree->right = *nodeVec.at(1);
But it throws an error saying that it doesn't recognize the '*' operator. Trying just
tree->left = nodeVec.at(0)
It says that I can't convert a node to a node*.
But if I use,
tree->left = &nodeVec.at(0)
It succesfully saves the address inside my left child.
I took a look at a couple of sites and answers and I think the one found here,
Dereference vector pointer to access element,
might've been the most relevant. I gave it a shot and threw so many errors, I didn't quite understand.
In short, from what i've read, I need to dereference the node inside my vector. But if it doesn't accept the '*' operator, how would one do that?
Thanks in advance!
You can access nodes in the vector like this:
node* p_left = nodeDev.at(0).left;
node copy_constructed_node(*(nodeDev.at(0).right));
You can also use your tree:
node* p_left = tree->left; // your code set this to &nodeVec[0]
More generally, I suggest you do some background reading on pointers (maybe here), or - better yet - consider whether a Standard container will satisfy your needs - e.g. std::map (tutorial here).

C++ returning global instance variable instead of it's copy

I have following problem:
I have this method in class Tree:
Node * nearest(const Point & point) const{
double minDistance = numeric_limits<double>::max();
Node * nearest = new Node;
for(Node *n : nodesVector){
int actualDistance = point.distance(n->point);
if(minDistance > actualDistance){
nearest = n;
minDistance = actualDistance;
}
}
return nearest;
}
This method is called from another class as follows:
void extend(const Point & rand){
Node *xNear = this->tree.nearest(rand);
Node *xRand = tree.add(rand, xNear);
std::vector<Node *> xNearSet = tree.rNearest(rand, this->RADIUS);
for(Node *node : xNearSet){
double c = node->cost + node->point.distance(rand);
if(c < xRand->cost){
xRand->parent = node;
}
}
for(Node *node : xNearSet){
double c = xRand->cost + node->point.distance(rand);
if(c < node->cost){
node->parent = xRand;
}
}
}
I need my method nearest and extend to not change variables in the tree after the extend execution, particularly the nearest node.
So I assumed that using pointer would make this for me, but unfortunately it has not so I have tried to create new pointer to Node, but this approach is not working for me either.
I would like to ask how can I implement it to not change the original node (use only it's copy that won't be treated as local variable or referenced the original one) that is used as nearest?
Thank you in advance for any suggestions.
EDIT:
Maybe I'll little bit reformulate the question. Now I have removed the memory leak, the line :
Node * nearest = new Node;
by line:
Node * nearest = nullptr;
But the main problem was and still is that after the local variable Node *xNear disappears then there are weird values assigned to the original node that was pointed by nearest.
Once you assigned nearest = n; the nearest variable no longer points at the newly created object, but to the one found in the nodesVector collection – and that one is returned.
if you want to return a copy, then don't overwrite nearest with an n pointer but rather assign values to the object pointed at:
*nearest = *n;
(be sure you have proper assignment operator defined in the Node class). This way you will return a copy of the nearest object.
So the biggest problem was that there was incorrectly initialized the initial nearest from the constructor (as a local variable without new) so it's values were somehow rewritten to some weird values. It has happened only at the time when there was as a xNear found the initial first from the Node values.
I guess your troubles are related to other operations in your code. How does Tree::add() work in your implementation? How is the tree populated in the first place?
My guess is that nearest is now in two locations in the tree, or a parent pointer is pointing to the same object it originates from.
Look at your tree in a debugger and navigate all the pointers. Additionally print every pointer in the destructor of Node to see whether you are pointing to free memory. Set a breakpoint there to find which scope was exited when the destructor was called.