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).
Related
Considering that this is my function:
void addtoSameList(const List &another){
for (Node *temp = new Node(*head); temp != nullptr; temp = temp -> next){
Node *ptr = other.head;
Node *temp2 = new Node;
temp2->value = temp->value;
while (ptr -> next != nullptr) {
ptr = ptr -> next;
}
ptr->next = temp2;
temp2->next = nullptr;
}
return;
}
where my goal is to append a linkedlist to itself, I do not know exactly what goes wrong.
If, for example, I have a linkedlist called n in the main function, where I then declare:
n.addtoSameList(n);
meaning that &other is going to be pointing at the same node as n, I figured that I would make a new node and deep copy the contents of n.
However, my two outputs are either that I end up in an infinite loop, or that some node ends up getting skipped.
How do I fix this issue?
This code has numerous issues. First, the interface doesn't suggest that the only use is to append a linked list to itself. Nor does it suggest that a deep copy is necessary in any other case.
So, lets adjust the requirements...
You want a member function that will append a copy of a linked list to the existing one. Then the case of self-appending naturally falls out of the problem description.
The approach here would be to step through the linked list that is passed in, carefully copying each node, then re-adjusting the pointers on the main linked list to point at your new node and the pointer in the new node to be set to appear to be the end of the list. This maintains a list invariant as the list is stepped through.
There is a pitfall here though. If you are self appending, you risk creating an infinite loop. So you should find the end node of the passed in list before you start this process and consistently use it to find out if you've gotten to the end of the list. If you maintain a tail pointer, this is trivial. If you don't, it means a list traversal.
Another way would be to simply create a copy first, carefully maintaining the pointer to the first node of the copy. Then just adjust the tail node's next pointer to point at the new list, and then adjust the tail node (if you maintain that pointer in the LinkedList data structure) to point at the tail node of the copy. And that's probably the way you should go. It's cleaner and more efficient. The main drawback is cleanup when doing exception handling. But, at your level, you shouldn't be concerned with that right now.
Here's an alternate approach. Create three pointers: ptrBegin, ptrEnd and ptrNew. ptrBegin points to the beginning of the linked list and traverse the linked list so that ptrEnd and ptrNew point to the last element of the linked list. Then increment ptrBegin until ptrBegin != ptrEnd at the same time copying the data at ptrBegin to a new node at ptrNew->next and increment ptrNew.
I'm new to C++ and I normally use Java, so I have a hard time to get into pointers and references. I have to do a variation of binary search tree with inner nodes and leaf nodes (only leafs contain the data).
class Node
Node *parent;
Node *left;
Node *right;
//other stuff
}
I need to implement operator<< which adds a new node with value to the tree.
//adding a node to tree
void operator<<(int value){
if(size == 0){
//stuff
} else {
Node* temp = root;
getLeaf(temp,value);
//other magic
//temp will be used to append a new node into tree,
//so it has to point to the actual node in the tree
delete temp;
}
}
The point of function getLeaf is to find a leaf (may or may not contain the desired value) and store it into temp, which needs to be accessible in the operator<< function.
int getLeaf( Node* temp, int value) const{
int depth = 0;
//goes trough all inner nodes until it finds specific leaf
while(temp->isInner()){
++depth;
if(value < temp->getValue()){ //searched value is smaller
temp = temp->getLeft(); // to left subtree
continue;
} else {
temp = temp->getRight(); //to rightsubtree
continue;
}
return depth;
}
I am really confused how to do this and what is the right combination of pointers and values. If I set
Node* temp = root;
getLeaf(temp,value);
won't root get overridden while traversing the tree in getLeaf function?
Plus I need temp to point to actual node in the tree, so I can append a new node into it.
Could you please explain?
Migrating from Java to C++ is a bit tough. Migrating from C++ to Java is equally tough. To make things easy you just need to experiment.
In C++, pointers are variables that point to the location of another variable in memory and references are pointers that syntactically behave like the variable whose address is pointed to.
When arguments are passed to a function, the function does NOT receive the original arguments but a copy of them. The work you did is implement the traversal based on the above concepts. So how does it all "magically" work?
Your function: getLeaf(Node *&temp, int value) searches the correct leaf node and assigns it to temp at which insertion is to be performed. temp here is a copy of a reference to the pointer temp(in operator <<). So when the reference temp is assigned to in getLeaf, the pointer temp in operator << it points to is modified.
If I set
Node *temp = root;
getLeaf(temp,value);
won't root get overriden while traversing the tree in getLeaf function?
Note here that temp and root are two different pointers that point to the same variable. The content of the pointers is the same, they aren't and hence root is NOT overridden, when temp is updated.
But there is a problem later on in the code. If you delete temp;, root will also be deleted at the end of insertion as delete deletes the content pointed to by the pointer. Do NOT delete a pointer that is not allocated by a new.
Provide a separate function to free the dynamically allocated memory used by the tree, and call it at the end when you are done experimenting.
A singly-linked list in C++, as I know it, is structured such that there is a root node which holds no values but the first element in a list of nodes. The nodes which are in the linked list headed by the root node (all of which hold data, and a pointer to the next node in the list).
A simple list skeleton (with no mutators or accessors) may look something like this:
class List {
private:
struct Node {
int value;
Node* next;
};
Node* root;
public:
List() {
root = new Node;
root->next = nullptr;
root->val = 0;
}
}
I would assume this all would mean that root->next would point to the first element in the list (meaning the root node is not the first element) correct?
A head node that isn't considered a regular node, can simplify (1)some list operations.
When there is one, it isn't considered part of the set of regular nodes, and if the list is abstracted, the head node is then usually not visible to client code.
Likewise one can have a tail node, but instead it's simpler to just use a circular list.
All that said, consider just using std::list where you need to insert or delete data without invalidating pointers to existing items.
And more in general, just use std::vector (except possibly for vector<bool>, where one might instead consider e.g. deque<bool>).
(1) E.g. deleting the first node that satisfies some criterion.
I feel really silly asking this, as it seems really simple, but I just can't figure it out. All I want to do is set the node pointer to the next node in the list. The function is from a teacher, I wrote the body, so I don't want to mess with the head of the function.
void LList::insert(int num, int at)
{
node* n = new node(num);
if (!n) throw runtime_error("Can't allocate node!");
if(!root || at == 0){
// if empty list - new node is root…
if (!root) root = n;
}
if(root){
node* nextNode = new node(num);
int numF = 0;
for (node* t = root; t != NULL ; t = t->next){
numF++;
if(numF == at){
n->next=t->next;
t->next=n;
}
}
}
}
Since it seems you are using n for the new node to be inserted into the linked list (I'm inferring that it's a singly linked list from the existing code and class name), there are a few things you have to do off the top of my head:
Identify the existing member of the list after which the new node will be inserted. You are making an attempt to do this already with that for loop, but in my opinion you may want to rewrite that as a while loop since you probably don't want it to keep iterating after the insertion position has been identified. Alternately, you could short-circuit out of the for loop with a break once you've found the right place for insertion, but I don't like that for stylistic reasons. :)
Set the newly inserted node's next pointer to the same location to which the next pointer of the node identified in #1.
Set the next pointer of the node identified in #1 to point at the new node, thus re-establishing the integrity of the chain.
Your code looks like it is attempting to do #2 and #3 out of order, which won't work. You're obliterating the value of t->next before you've had a chance to point n->next at it.
Finally, you may need to define some behavior to which you can fall back in case you are adding to a position not already defined in the list (i.e. inserting into the fourth position of a linked list that currently has three elements). You may need to re-jigger your loop to terminate when t->next is null rather than when t itself is null - otherwise you lose the hook to be able to connect the (currently) last element of the list to your new node.
This question is probably one of the most popular questions around and while searching for a solution, I've found many but the code below was the most suitable for me.
What it actually does is that it creates another list and iterates through the old list and add the element always to the head of the new list.
Node *reverseList(Node *oldList)
{
Node* newList=NULL;
while(oldList!=NULL)
{
Node *temp=oldList;
oldList=oldList->next;
temp->next=newList;
newList=temp;
}
return newList;
}
However when I decided to re-implement this idea without looking at this code I've changed place of the oldList=oldList->next; and put it after the newList=temp.
My question is does it really make a difference? I couldn't comprehend the reason because after all you are iterating through the oldList. Why would it require to be done immediately after the *temp declaration?
After doing
Node *temp = oldList;
both pointers point at the same place. Since
temp->next = newList;
will overwrite the next pointer of oldList (because it points to the same thing as temp at this stage), you need to update oldList from its next pointer first.