The structure of the node is as followed:
struct Node {
int value;
Node *next;
};
// construct a new node
Node * cons( int x, Node* p) {
return new Node{x, p};
}
Now if I were to type in my main body:
Node *p;
p = cons(3,nullptr);
p = cons(2,p);
p = cons(1,p);
p = cons(4,p);
Is there a better value to start off with for my first node instead of nullptr?From what I understand this is 4 Nodes in order. Is that correct? Node value 3 is the first on the list. So this function would search my linklist in order as in goes to view node value 3, 2,1,4,then empty node.
//search linklist in order for value x
bool searchInOrder(int x, Node *p){
while(p->next != nullptr){
if(x == p->value)
return true;
p = p->next;
}
return false;
}
Question:
Is there a better value to start off with for my first node instead of nullptr?
Answer:
That is the best way to create the first node of a linked list.
Question:
From what I understand this is 4 Nodes in order. Is that correct? Node value 3 is the first on the list. So this function would search my linklist in order as in goes to view node value 3, 2,1,4,then empty node.
Answer:
Yes there are 4 Nodes. However, the Node with value 3 is not the first Node in the list.
After
p = cons(3,nullptr);
The list is:
+---+ +-----+
+ p + ---> | 3 | ---> NULL
+---+ +-----+
After
p = cons(2,p);
The list is:
+---+ +-----+ +-----+
| p | ---> | 2 | ---> | 3 | ---> NULL
+---+ +-----+ +-----+
After
p = cons(4,p);
The list is:
+---+ +-----+ +-----+ +-----+ +-----+
| p | ---> | 4 | ---> | 1 |---> | 2 | ---> | 3 | ---> NULL
+---+ +-----+ +-----+ +-----+ +-----+
Related
This is the code for displaying a linked list from a udemy tutorial here we will take an array and store those values in a linked list. I didn't understand how the code works. in the below code where we are storing the address of the next node how last->next=temp; works where I didn't create a last node like last=new node; I only created the last pointer. I didn't get it can someone explain to me how it's working
#include <iostream>
using namespace std;
class Node{
public:
int data;
Node* next;
};
int main() {
int A[] = {3, 5, 7, 10, 15};
Node* head = new Node;
Node* temp;
Node* last;
head->data = A[0];
head->next = nullptr;
last = head;
// Create a Linked List
for (int i=1; i<sizeof(A)/sizeof(A[0]); i++){
// Create a temporary Node
temp = new Node;
// Populate temporary Node
temp->data = A[i];
temp->next = nullptr;
// last's next is pointing to temp
last->next = temp;
last = temp;
}
// Display Linked List
Node* p = head;
while (p != nullptr){
cout << p->data << " -> " << flush;
p = p->next;
}
return 0;
}
The best way to figure out pointers is to draw boxes and arrows with pen(cil) and paper.
Here is a (sad) ASCII rendition of what happens:
head->data = A[0];
head->next = nullptr;
last = head;
head points to a newly created node, and last points to the same place as head:
head
|
v
+------+------+
| data | next |
| |(null)|
| | |
+------+------+
^
|
last
Next,
// Create a temporary Node
temp = new Node;
// Populate temporary Node
temp->data = A[i];
temp->next = nullptr;
looks like this:
head temp
| |
v v
+------+------+ +------+------+
| data | next | | data | next |
| |(null)| | |(null)|
| | | | | |
+------+------+ +------+------+
^
|
last
Then
last->next = temp;
changes the next member of the node last points to (in the first iteration, this is the same node as head points to):
head temp
| |
v v
+------+------+ +------+------+
| data | next | | data | next |
| | ---------->| |(null)|
| | | | | |
+------+------+ +------+------+
^
|
last
And, lastly, you make last point to the most recently created node:
last = temp;
which gives
head temp
| |
v v
+------+------+ +------+------+
| data | next | | data | next |
| | ---------->| |(null)|
| | | | | |
+------+------+ +------+------+
^
|
last
and then you repeat the loop from there.
You have already initialized the variable last as head using last = head just before the for loop. This is done to ensure the original head does not get modified while adding other nodes to the list. In each iteration, the last node is used to keep track of the last node in the linked list so that every new node gets added to the end of the linked list.
in the below code where we are storing the address of the next node how last->next=temp; works where I didn't create a last node like last=new node; I only created the last pointer.
last is always just a pointer. It starts out equal to head, which is a pointer to the first node. In your loop, you create a new node that temp points to, and then you set the next field of the node to which last currently points to temp, and then you change last so that it now points to that same node, which is the new last node.
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.
Below is the code,
#include<bits/stdc++.h>
using namespace std;
class node{
public:
int data;
node * next;
node(){
this->next = NULL;
}
node(int data){
this->data = data;
this->next = NULL;
}
};
class linkedList{
public:
node * head;
node * tail;
linkedList(){
this->head = NULL;
}
void getTail(node *& t){
t = head;
while(t->next != NULL){
t = t->next;
}
}
void insertAtEnd(int data){
node * newNode = new node(data);
if(head == NULL){
head = newNode;
return;
}
node * temp = head;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = newNode;
}
void print(){
node * temp = head;
while(temp != NULL){
printf("%d->", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
void swap(node *& a, node *& b){
node * temp = a;
a = b;
b = temp;
}
void swapNode(node ** start, node ** end){
swap(*start, *end);
swap(((*start)->next), (*end)->next);
}
};
int main(){
///////////////////////////////////////
linkedList * ll1 = new linkedList(); //
ll1->insertAtEnd(6); //
ll1->insertAtEnd(2); //
ll1->insertAtEnd(1); //
ll1->insertAtEnd(3); //
ll1->print(); /////////////////////
ll1->swapNode(&ll1->head, &ll1->head->next->next->next);// ----> This is working
//////////////////////////////////////////////////////////
linkedList * ll2 = new linkedList();
ll2->insertAtEnd(6);
ll2->insertAtEnd(2);
ll2->insertAtEnd(1);
ll2->insertAtEnd(3);
ll2->print();
node * tail;
ll2->getTail(tail);
ll2->swapNode(&ll2->head, &tail); // This is not working // Going into a infinte loop
ll2->print();
}
When the tail node is stored in some other variable there seems be a forever loop.
While the code is working when the tail node is given by traversing to last using next pointer.
So, below is the output for the first example of the linked list, that is,
6->2->1->3->NULL
1->2->6->3->NULL
For the linked list #2, the output goes like this
6->2->1->3->NULL
3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2->1->3->2-> there's no ending
When you swap two nodes a and b you must also fix the pointers reaching a and reaching b. For example
x1 -> x2 -> a -> x3 -> x4 -> b -> x5 -> x6 -> NULL
to swap nodes a and b to don't need to fix only a.next and b.next but also x2.next and x4.next.
That part of code is missing from your implementation.
Pictures often help when dealing with linked lists. Here is the starting list.
head
|
V
------------ ------------ ------------ ------------
| 6 | next | -> | 2 | next | -> | 1 | next | -> | 3 | NULL |
------------ ------------ ------------ ------------
Now we'll call ll1->swapNode(&ll1->head, &ll1->head->next->next->next), which adds two variables to the picture.
start
|
V
head end
| |
V V
------------ ------------ ------------ ------------
| 6 | next | -> | 2 | next | -> | 1 | next | -> | 3 | NULL |
------------ ------------ ------------ ------------
Next is the call to swap(*start, *end), which swaps the head pointer and the next pointer in the node whose data is 1. So the head pointer will point to the 3 node, while the 1 node will point to the 6 node.
start
|
V
end head
| |
V V
------------ ------------ ------------ ------------
| 6 | next | -> | 2 | next | -> | 1 | next | | 3 | NULL |
------------ ------------ ------------ ------------
^ |
| |
L---------------------------------------
Finally, the call to swap(((*start)->next), (*end)->next), which swaps the next pointers in the nodes whose data is 3 and 6. So the 3 node will point to the 2 node, while the 6 node's pointer will become null.
start
|
V
head
|
V
------------
| 3 | next |
------------ end
| |
V V
------------ ------------ ------------
| 6 | NULL | | 2 | next | -> | 1 | next |
------------ ------------ ------------
^ |
| |
L---------------------------------------
Hooray! The nodes were swapped.
Now look at the call ll2->swapNode(&ll2->head, &tail);, which adds three variables to the initial picture.
start end
| |
V V
head tail
| |
V V
------------ ------------ ------------ ------------
| 6 | next | -> | 2 | next | -> | 1 | next | -> | 3 | NULL |
------------ ------------ ------------ ------------
Next is the call to swap(*start, *end), which swaps the head pointer and tail (not the tail pointer of the list, but the variable local to main()).
end start
| |
V V
tail head
| |
V V
------------ ------------ ------------ ------------
| 6 | next | -> | 2 | next | -> | 1 | next | -> | 3 | NULL |
------------ ------------ ------------ ------------
There's already a noticeable difference from the first case in that the nodes of the list are unchanged. Hmm... well, let's keep going and call swap(((*start)->next), (*end)->next), which swaps the next pointers in the nodes whose data is 3 and 6. So the 3 node will point to the 2 node, while the 6 node's pointer will become null. This is what happened in the first case, so will it work out?
end start
| |
V V
tail head
| |
V V
------------ ------------ ------------ ------------
| 6 | NULL | | 2 | next | -> | 1 | next | -> | 3 | next |
------------ ------------ ------------ ------------
^ |
| |
L---------------------------------------
PROBLEM! We are left with a cycle! What happened to the step where the 1 node was changed to point to the 6 node? That's right, we changed tail instead, and the result was disaster.
I would recommend three main things to move your code to more robust ground. (That is, don't try to fix your current error yet. Do these first as they'll change the playing field.)
Get rid of #include<bits/stdc++.h>; instead include the headers you need. For this example, you need just #include <cstdio>.
Make node a private implementation detail of linkedList. Robustness tends to increase along with encapsulation. If no one knows the data structures used by linkedList, you limit what other code can do. With fewer possibilities to account for, it's easier to make sure you accounted for all of them.
Don't declare a field (linkedList::tail) that is never used. Someone will want to use that field at some point without realizing it contains garbage.
(There are other improvements to be made. These three are the most important in my view.)
Below is the code for swapping nodes without changing data. I wonder whether swapping the next pointers of nodes required? Will swapping the current nodes doesn't swap the next pointers? Why?
void swapNodes(Node** head_ref, int x, int y)
{
// Nothing to do if x and y are same
if (x == y)
return;
Node **a = NULL, **b = NULL;
// search for x and y in the linked list
// and store therir pointer in a and b
while (*head_ref) {
if ((*head_ref)->data == x) {
a = head_ref;
}
else if ((*head_ref)->data == y) {
b = head_ref;
}
head_ref = &((*head_ref)->next);
}
// if we have found both a and b
// in the linked list swap current
// pointer and next pointer of these
if (a && b) {
swap(*a, *b);
swap(((*a)->next), ((*b)->next));
}
}
void swap(Node*& a, Node*& b)
{
Node* temp = a;
a = b;
b = temp;
}
Thank You.
whether swapping the next pointers of nodes required?
Yes it is required because the original nodes take place in different positions of the list.
Will swapping the current nodes doesn't swap the next pointers?
Yes, swapping current nodes doesn't swap the next pointers. Swapping current nodes means only swapping only pointers that point to the current nodes.
Consider for example the list
| A |next B| -> | B |next C| -> | C |next D| -> | D |next nullptr|
and let's assume that you need to swap nodes B and D. Then you'll get
---------------------
| |
| A |next D| ... | B |next C| -> | C |next B| ... | D |next nullptr|
| |
----------------------------------------------
So after the first swapping the node A points to node D but node D "points" to nullptr. Nodes B and C will be lost if not to swap their data members next.
Thus you need also to swap their data members next
--------------------------
| |
| A |next D| ... | B |next nullptr| | C |next B| ... | D |next C|
| |
---------------------------------------------------
and as result you'll get
| A |next D| -> | D |next C| -> | C |next B| -> | B |next nullptr|
Swapping the current nodes won't be enough.
When swapping a and b, their address is changed so their place in the list will be replaced
But you do not change the inner fields of each node.
Nodes Illustraion:
a - b - c - d
Let's take node a and c.
a->next == &b (True)
c->next == &d (True)
If we swap the nodes like this:
c - b - a - d
The address of node c and node a will change, but the list would look the same since their ->next values will not change
If we also swap the ->next values, the list will be really swapped
void add_node(int n) {
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
if(head == NULL) {
head = tmp;
tail = tmp;
}
else {
tail->next = tmp;
tail = tail->next;
}
}
in the else statement, why cant i directly assign tail=tmp; instead of tail=tail->next; is there anything Im missing? Thanks in advance!
Lets take a small simple list:
+-------+ +-------+ +-------+
| node1 | --> | node2 | --> | node3 |
+-------+ +-------+ +-------+
^ ^
| |
head tail
Now to add a new node at the end of the list, we first add the new node to the list, by making the tails next pointer point to the new node:
+-------+ +-------+ +-------+ +-------+
| node1 | --> | node2 | --> | node3 | --> | node4 |
+-------+ +-------+ +-------+ +-------+
^ ^
| |
head tail
This is what the assignment tail->next = tmp does.
Then we update tail to point to the new tail:
+-------+ +-------+ +-------+ +-------+
| node1 | --> | node2 | --> | node3 | --> | node4 |
+-------+ +-------+ +-------+ +-------+
^ ^
| |
head tail
This is what the assignment tail = tail->next does. Of course, this could also be done by doing tail = tmp.
The order of the two assignments is important.
Now if you do it the opposite way, by assigning tail = tail->next first, when we have
+-------+ +-------+ +-------+
| node1 | --> | node2 | --> | node3 |
+-------+ +-------+ +-------+
^
|
head
You no longer have a tail! You don't know where the list ends, and where to insert the new node unless you loop over the whole list to find a node whose next pointer is a null pointer.
You can do that, but it will not produce the correct result. Trace it with a debugger if you can't figure out why from looking at the code.