Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
So I'm looking at a linked list with nodes setup like this
struct node {
node *next;
node **prev;
};
node *rel_list;
Can someone explain how the pointer operations work in the following code block (from the node creation function) especially line 5.
1 node *r;
2 r->next = rel_list;
3 r->prev = &rel_list;
4 if (rel_list)
5 rel_list->prev = &r->next;
6 rel_list = r;
In most linked list implementations, the pointers point to a node, not to a pointer:
+------+
| prev |
+------+
| data |
+------+
| next |
+------+
+------+ +------+ +------+
| 0 | +------| | +------| |
+------+ | +------+ | +------+
| A |<--+ +-->| B |<--+ +-->| C |
+------+ | +------+ | +------+
| |------+ | |------+ | 0 |
+------+ +------+ +------+
In your code, you are making the previous pointer point to the next pointer not the previous node.
Edit 1: Example
node * ptr_node = new node;
ptr_node->prev = nulptr;
ptr_node->next = nulptr;
// Insert at the head
ptr_node->prev = head_pointer;
ptr_node->next = head_pointer->next;
head_pointer = ptr_node;
Linked lists are, IMHO, better drawn (pictures) to grasp concepts. Go through the example above and "draw" each step.
Related
This is the solution to printing elements of a linked list.
Why isn't it Node *current = new Node; and then current = head;?
void printLinkedList(Node* head)
{
Node *current = head;
while(current!=NULL){
cout << current -> data << endl;
current = current -> next;
}
}
This is a great spot to draw pictures!
Imagine we have a linked list pointed at by head:
head
|
v
+------+ +-----+ +-----+ +-----+
| i'm | -> | the | -> | bad | -> | guy | -> null
+------+ +-----+ +-----+ +-----+
If we use the line of code
Node *current = new Node;
then memory looks like this:
head current
| |
v v
+------+ +-----+ +-----+ +-----+ +------+
| i'm | -> | the | -> | bad | -> | guy | -> null | duh! | -> ?
+------+ +-----+ +-----+ +-----+ +------+
The goal of the function is to print the existing list pointed at by head, but here we've got a pointer to a new linked list cell that isn't a part of the existing list. As a result, we've committed two Programming Sins:
We've allocated memory for an object we don't need.
We've broken the contract we made with the client.
On the other hand, if we write
Node *current = head;
then memory looks like this:
head
|
v
+------+ +-----+ +-----+ +-----+
| i'm | -> | the | -> | bad | -> | guy | -> null
+------+ +-----+ +-----+ +-----+
^
|
current
Here, current is now pointing into the existing list, so we can walk the list to find what we need. No new nodes need to be created here, so we don't create any new nodes.
Generally speaking, in C++ you should avoid using new unless you really truly want to create a new linked list cell. In this case, we don't want to do that, which is why we create current and have it point to an existing linked list cell.
Hope this helps!
Because the node already exists.
new would create a new one.
You don't need or want to create a new one.
You just want to "use" a pointer to an existing node.
Here's it's just the function argument being copied into a variable with a different name. It's actually completely unnecessary.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Can someone please explain the code below:
void reverseList(node **href){
node *first;
node *rest;
if(*href == NULL){
return;
}
first = *href;
rest = first->next;
if(rest == NULL){
return;
}
reverseList(&rest);
first->next->next = first;
first->next = NULL;
*href = rest;
}
Note : href is the head reference of the linked list.
What i don't understand is the last statement => *href = rest
as this step will happen when the recursion is unfolding wouldn't this make the second node from the start head ref but we want the last node as our head ref.
How will this make the last node as our head_ref?
reverseList will update *href so it points to the new head of the list it's given; this is the node that used to be last.
I think what could be confusing you is that all calls update *href to the same value; when the recursive call returns, it will point to the last node of the input, which is the first node of the result.
This value is only set when the recursion terminates.
I'm going to rename first and rest in an attempt to clarify this.
The first condition,
if(*href == NULL){
return;
}
is there to handle the case when you start with the empty list.
The following handles the common base case, where you eventually reach a one-element list:
old_head = *href;
/* "If the list has exactly one element, do nothing." */
if(old_head->next == NULL){
return;
}
Then, you recurse (keep in mind that the parameter is both an "in" and an "out" parameter)
new_head = old_head->next;
reverseList(&new_head);
and now, through the power of recursion, new_head points to the head of the reversed "rest of the list".
This is also the pointer that's going to be our result.
(The last node of the tail is also the last node of the entire list, right?)
What we need now is to set up the end of the new list (the initial part of it has already been reversed during the recursion).
Since we saved old_head before, we can reverse the next pointer of the node that used to follow it:
old_head->next->next = old_head;
old_head->next = NULL;
that is, this
old_head new_head
| |
v v
+---+ +---+ +-----------------------------+
| ------>| | <----- | reversed |
| | | -----> | former continuation of list |
+---+ +---+ +-----------------------------+
becomes this (old_head->next->next = old_head;)
old_head new_head
| |
v v
+---+ +---+ +-----------------------------+
| ------>| | <----- | reversed |
| |<----- | | former continuation of list |
+---+ +---+ +-----------------------------+
and then (old_head->next = NULL;)
old_head new_head
| |
v v
+---+ +---+ +-----------------------------+
| X | | | <----- | reversed |
| X |<----- | | former continuation of list |
+---+ +---+ +-----------------------------+
Then, we update the parameter so our caller also gets a pointer to the new head:
*href = new_head;
I am just wondering, in a linked list what is the difference between the two:
node1 = node2
and
node1->next = node2
The first line makes me a bit confused.
I'm assuming from context here that node1 and node2 are pointers to nodes (for example, they might have a type like Node *). If that's not the case, please let me know!
If node1 and node2 are pointers, remember that there is a difference between pointers to nodes and actual, honest-to-goodness node objects. The pointers are just a way of saying "look over there and you'll find a node." The nodes themselves are actual objects containing data and links to other nodes.
For example, if you have two node pointers node1 and node2 that point to nodes, perhaps it looks like this:
+----------+ +----------+
| | -----------> | data! |
+----------+ +----------+
node1 | next! | -----> ...
+----------+
+----------+ +----------+
| | -----------> | data! |
+----------+ +----------+
node2 | next! | -----> ...
+----------+
If you write node1->next = node2, you're saying "follow the pointer named node1 to see what node it points at, find the next pointer in that node, and change it to point to wherever node2 points." That makes things look like this:
+----------+ +----------+
| | -----------> | data! |
+----------+ +----------+
node1 | next! | -----> ...
+----------+
|
|
v
+----------+ +----------+
| | -----------> | data! |
+----------+ +----------+
node2 | next! | -----> ...
+----------+
Writing node1 = node2 means "change node1 to point to whatever node node2 is pointing at." That looks like this:
+----------+ +----------+
| | ------+ | data! |
+----------+ | +----------+
node1 | | next! | -----> ...
| +----------+
| |
| |
| v
+----------+ | +----------+
| | ------+----> | data! |
+----------+ +----------+
node2 | next! | -----> ...
+----------+
Fundamentally, there's no deep difference between these operations. They both change where some pointer is pointing. The difference is whether you're changing the next pointer inside of a node object or whether you're changing which node node1 points at.
Whenever you have a question about what a line of code does that involves pointers or linked lists or the like, I highly recommend drawing pictures like the ones shown here. Building a visual intuition for what links you're creating and what links you're breaking is one of the best ways to better understand how code works. Plus, it's great for debugging!
I am currently about to implement a multi-way tree in c++, but I am still not sure about what exactly they are. I have read a few documentations, but I am still confused because of the lack of pictures or visualization provided.
Lets say I want a 3 way tree, according to online web notes it means each node can have at most 3-1 = 2 elements and each node can have at most 3 children. Below I have drawn some trees that I am not sure if they are 3-way trees, can someone please verify I am understanding this correctly? Thank you!
Also, if I have a 2 way tree, does that mean I have a binary tree as well? O.o?
My understanding of a multi-way tree is the number of subtrees that can be traversed from a single node.
+---+
| D |
+---+
^
|
|
+---+ +------+ +---+
| A | <-- | Root | --> | B |
+---+ +------+ +---+
|
|
V
+---+
| C |
+---+
The diagram above shows a multi-way tree because the root has more than 1 child.
Usually 2 children per node (except leaf nodes) indicates binary trees.
There are many different kinds of binary trees.
See also B-Tree and B*Trees.
Edit 1:
Another view:
+------------------------+
| Root +
+------------------------+
| | | |
V V V V
+---+ +---+ +---+ +---+
| A | | B | | C | | D |
+---+ +---+ +---+ +---+
The C++ program I'm working on is designed to create a custom doubly Linked List class in C++ by utilizing an indefinite number of node struct pointers with a data value and two pointers inside. That's the premise of this program. Can't use the STL LinkedList class, have to make my own.
This being said, how do you create a class member variable that doesn't have a specific amount of pointers to nodes? I don't want to initialize fifty nodes when declaring the class, but then only use ten of them. and at the same time, I don't want to initialize only 5 and then have to use more than that 5. Is there a way to dynamically add node pointers to a linked list class in C++, when node pointers are considered a member variable?
Am I even going about this the right way? And if so, how will I go about doing this?
Picture this:
+----------+-------+------+
| Previous | Data | Next |
| Node | Field | Node |
+----------+-------+------+
A node with two link fields and a data field.
(Linked lists are always easier to understand when you draw them.)
We could have two of them:
+----------+-------+------+
| Previous | Data | Next |
| Node | Field | Node |
+----------+-------+------+
^ |
| V
+----------+-------+------+
| Previous | Data | Next |
| Node | Field | Node |
+----------+-------+------+
The Previous Node field of the 2nd node points to the first. The first node has no predecessors, so it's Previous Node field is empty.
Similarly, the Next Node field of the first node points to the 2nd node. The 2nd node has no successor, so the Next Node field of the 2nd node is empty.
This is what I believe the requirements want: a doubly linked list using pointers.
Edit 1: Three nodes
+----------+-------+------+
| Previous | Data | Next |
| Node | Field | Node |
+----------+-------+------+
^ |
| V
+----------+-------+------+
| Previous | Data | Next |
| Node | Field | Node |
+----------+-------+------+
^ |
| V
+----------+-------+------+
| Previous | Data | Next |
| Node | Field | Node |
+----------+-------+------+
As you can see, to visit (traverse) the nodes in a forward manner, you follow the link field of one node to get to the next node. Similarly, to go in a backwards manner, you follow the Previous Node link to get to a node's predecessor.
A nice issue about the links is that you only need to change the link fields in order to insert a node in the middle of the list. Drawing of the insertion processes is left as an exercise for the reader.
Edit 2: The Container Class
The Linked List is a container of nodes. For simple implementations, the Container class should not be a Node.
The Container has-a pointer to the first node and optionally a pointer to the last node:
+------+-------+
| Last | First |
| Node | Node |
+------+-------+
| |
| +---------------+
| |
| V
| +----------+-------+------+
| | Previous | Data | Next |
| | Node | Field | Node |
| +----------+-------+------+
| ^ |
| | V
| +----------+-------+------+
| | Previous | Data | Next |
| | Node | Field | Node |
| +----------+-------+------+
| ^ |
| | V
| +----------+-------+------+
| | Previous | Data | Next |
+->| Node | Field | Node |
+----------+-------+------+
By using a container class, you don't need to worry about an using an empty node as the first node. Here, we use a simple pointer to point to the first node. Additionally, there is a pointer to the last node.
The pointer to the last node speeds up the operation of appending nodes to the list. Without this pointer, you would have to traverse all the nodes to find the last one, which takes a lot of time.