Iteration through linked list recursively - c++

In this piece of code
Node* insert(int num, Node *head) {
if (head == NULL|| num <= head->next)
return addNewNode(num, head);
head->next = insert(num, head->next);
return head;
}
Why is it
head->next = insert(num,head->next);
and not
head = insert(num,head->next);
I understand we have to traverse through the singly linked list and I thought "head->next" inside the function call takes care of that.

When you don't insert the element as the first node, you want to keep the head and insert into the list's tail.
head->next = insert(num, head->next); replaces the tail with the modified one.
head = insert(num, head->next); would ignore the head and replace it with the result of inserting an element in its tail.
Example: say that we have
head
|
v
1 -> 3 -> X
and want to insert 2.
The recursive insertion returns a pointer to
2 -> 3 -> X
and pointing head->next at this gives
head
|
v
1 -> 2 -> 3 -> X
while your suggestion would give
head
|
v
1 -> 2 -> 3 -> X
and you've lost the 1.

Related

Does this function add new node to the end of the linked list? [closed]

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 3 years ago.
Improve this question
I wonder, does this insert a node to the end of the list? Let's say that I have a linked list of 1->2->3->8->NULL and I want to insert a new node with data of 9. It will traverse to NULL recursively. When head is pointing at NULL, head = nextNode is not working. Or is head still pointing at node of 8? Thank you.
I only want to know can this insert a node at the end of the list? I don't think so.
void insert(Node *&head, int data) {
if (head == NULL || data <head ->data) {
Node *nextNode = new Node;
nextNode->data = data;
nextNode->next = head;
head= nextNode;
} else {
insert(head->next, data);
}
}
This condition
if ( head == NULL || data < head->data )
is not evaluates to true for each node in the list that contains the sequence of nodes like
1->2->3->8->NULL
because the value of data 9 is not less than any value of data of existent nodes.
So the function will be recursively called until the next node will be equal to NULL (that is when the function will be called with reference to the data member next of the last node that is equal to nullptr). As a result the new node is appended to the tail of the list. That is the last pointer in the list with the value NULL will be substituted for the new node. Thus nodes are inserted in the list in the ascending order.
Here is a demonstrative program.
#include <iostream>
struct Node
{
int data;
Node *next;
};
void insert( Node * &head, int data )
{
if ( head == nullptr || data < head ->data )
{
head = new Node { data, head };
}
else
{
insert( head->next, data );
}
}
std::ostream & output( const Node *head, std::ostream &os = std::cout )
{
for ( ; head != nullptr; head = head->next)
{
os << head->data << " -> ";
}
return os << "null";
}
int main()
{
Node *head = nullptr;
for ( int data : { 3, 8, 1, 2, 9 } )
{
insert( head, data );
output( head ) << '\n';
}
return 0;
}
Its output is
3 -> null
3 -> 8 -> null
1 -> 3 -> 8 -> null
1 -> 2 -> 3 -> 8 -> null
1 -> 2 -> 3 -> 8 -> 9 -> null
To make it clear consider a list that contains two nodes with data 1 and 3.
head |node A with value 1|next B| |node B with value 3| next nullptr|
|______________| |______________|
and you are trying to insert a node with the value 2.
The function is called with
insert( head, 2 );
head->data equal to 1 is not greater than 2. SO the function is called like
insert( ( node A )->next, 2 );
( node A )->next->data equal to 3 is greater than 2.
So you have to substitute ( node A )->next with the address of the newly created node with the value 2.
head |node A with value 1|next C| |node B with value 3| next nullptr|
|______________| | |
| |
|node C with value 2 | the value of next B of node A|
this function is completely wrong cos it will cause memory leakage. and it will only work for first iteration.
I am writing u the code but it wont help u learn.
if(head==NULL)
{
Node *nxtNode=new Node;
nxtNode->data=data;
head=nxtNode;
nxtNode->next=NULL;
return;
}
if(head->next==NULL||data<head->next->data)
{
Node *nxtNode=new Node;
nxtNode->data=data;
nxtNode->next=head->next;
head->next=nxtNode->next;
return;
}
else
{
insert(head->next,data);
}
It inserts a new node into the linked list into the sorted position. At least, that is the intent.
Here is the compiled code working with input that demonstrates the behavior: link.
The line of interest: if (head == NULL || data < head->data)
The new entry is placed in the position that this condition passes.

Writing pop() method for LinkedStack in O(1)

How would I write a pop() method for LinkedStack in O(1)?
I have two private data members in my LinkedStack class: ListNode* head and ListNode* tail.
head points to the beginning of the LinkedStack, and tail points to the end of the LinkedStack.
pop() will remove the ListNode being pointed to by tail, then tail will point to the ListNode that was before tail.
Knowing this, how would I write pop() in O(1)? Obviously, I can write a for loop that grabs the previous ListNode right before tail, but then pop() wouldn't be O(1).
Since this is for homework, I'm not looking for code solutions, just maybe a hint in the right direction.
Edit: One solution I possibly see is having a ListNode* prev data member, which always points to the previous ListNode before tail. But I feel like there's a more efficient way....
Edit2: Thanks #user4581301. Assume that pop() will not be called when LinkedStack is empty.
As you state, any situation where you have to traverse the list to locate a specific element is going to make the constant time requirement impossible to meet. This includes a singly-linked list where you're pushing items on to the end. A doubly-linked list will be easier since you can then get from the tail to the penultimate item without traversal.
However, I'm not sure why you're pushing on to the end. If you were to push new elements on the the front of the list, achieving constant time for both push and pop is trivial.
By that, I mean (pseudo-code since, as you mention, "this is for homework"):
def push(x):
allocate node # get new node and set data.
node.data = x
node.next = head # insert at head of list
head = node
def pop():
assert head != null # catch pop on empty stack
node = head # get first node and data
retval = node.data
head = head.next # set head to be second node
free node # free node and return data
return retval
You can see that there is no traversal of the list for either operation. First, pushing 7 on to a stack of primes:
Starting list:
head
\
5 -> 3 -> 2 -|
Create new node, point to current head:
head
\
7 -> 5 -> 3 -> 2 -|
Point head at new node:
head
\
7 -> 5 -> 3 -> 2 -|
Now let's pop that same value.
Starting list:
head
\
7 -> 5 -> 3 -> 2 -|
Save head as node, and value to return (7):
head
\
7 -> 5 -> 3 -> 2 -|
/
node
Adjust head:
head
\
7 -> 5 -> 3 -> 2 -|
/
node
Free node and return stored value (7):
head
\
5 -> 3 -> 2 -|

How the last line of following recursive program is working?

I was studying Linked List and then I found a code for reversing the Linked List recursively. Here is the C++ code.
void recursiveReverse(node*& head)
{
node* first;
node* rest;
/* checking for an empty list */
if (head == NULL)
return;
first = head;
rest = first->next;
/* List has only one node */
if (rest == NULL)
return;
recursiveReverse(rest);
first->next->next = first;
first->next = NULL;
/* fix the head pointer */
head = rest;
}
I understood the whole code except the last line. Because according to me, the rest pointer is also updated similarly as the first pointer during unwinding of the recursion and therefore, at the end of this code, the head will not point to the last node.
Here's my interpretation of the following code.
Let's take a Linked List 1 -> 2 -> 3.
Initially, first will store the address of the head node and rest
will contain the address of the node 2.
Now, since rest is not NULL, therefore, recursiveReverse(rest) will be called.
Now, first will point to node 2 and rest will point to node 3.
Again, rest is not NULL, therefore, recursiveReverse(rest) will be called.
Now, first will point to node 3 and rest will contain NULL.
After that, the recursion will start unwinding and first will be back to node 2 and the rest will be back to node 3.
Now, the statement first -> next -> next = first; will cause the next part of node 3 to point to node 2 and the Linked List will become 1 -> 2 <- 3. The next part of node 2 will contain NULL and since head = rest, therefore, head will also point to last node as the rest pointer.
After that, first will point to node 1 and the statement first -> next -> next = first; will cause the next part of node 2 to point to node 1 and the Linked List will become 1 <- 2 <- 3. The next part of the node 1 will contain NULL and the statement head = rest will cause the head to point to node 2 and not the node 3 since, the rest (which is first -> next) is currently at node 2.
Can anyone please explain where I am wrong in interpreting this code?
Maybe there are other misinterpretations, but I assume that the basic one concerns your interpretation "the statement head = rest will cause the head to point to node 2 and not the node 3 since, the rest (which is first -> next) is currently at node 2".
At the end, head will point to the last node of the initial list. Let's consider a simplified/shortened portion of your code:
rest = head->next;
if (rest == NULL) // end of list reached; head points tho the last node
return;
recursiveReverse(rest); // if the end is not reached, go forward with the next node (i.e. the value of head->next
head = rest; // reset head to the (shared) value of rest.
This is because statement recursiveReverse(rest) will be called again and again until head->next will be NULL, i.e. the end of the list is reached. The very last run of recursiveReverse returns because head->next == NULL, and in the caller, variable rest points to the last node.
Now note that "rest" is shared among all the calls to recursiveReverse, as it is passed by reference. So statement head = rest will be called for every instance of recursiveReverse called so far, but - as rest is shared among all the calls and is not changed after the recursive calls - statement head = rest will assign the head always to the same value of rest, which remains the one pointing to the last node.
Puh - hope this is comprehensive.
Anyway, doing recursive functions with parameters passed by reference is usually hard to understand; Typically things become easier when recursive functions manage their private states but use the return value to coordinate the results. If you arrange the code such that you have node* reverseRecursive(node *current), your code will become easier to understand.
It looks like in step 8. you forgot that head in void recursiveReverse(node*& head) is a reference. So when you recursively call recursiveReverse(rest); then rest is passed by reference. That means that, when inside the recursion, head is a reference to the rest variable in the calling function. Therefore when it was changed to point to 3 inside the recursion then rest in the calling function was also changed.
If this sounds confusing then drawing up the local variables on the stack might help:
1) Initially, head will be a reference to the pointer to the node passed to the function, first will store the address of the head node and rest will contain the address of the node 2.
The stack will look like this (only showing local variables and ignoring whatever was already there when calling the function):
====================================
head: reference to original head
first: node 1
rest: node 2
2) Now, since rest is not NULL, recursiveReverse(rest) will be called.
3) Now, head will reference rest in the calling function, first will point to node 2 and rest will point to node 3.
The stack will look like this:
====================================
head: reference to original head
first: node 1
rest: node 2 <---------------+
==================================== |
head: reference to ---------------+
first: node 2
rest: node 3
4) Again, rest is not NULL, therefore recursiveReverse(rest) will be called.
5) Now, head will reference rest in the last calling function, first will point to node 3 and rest will contain NULL.
The stack will look like this:
====================================
head: reference to original head
first: node 1
rest: node 2 <---------------+
==================================== |
head: reference to ---------------+
first: node 2
rest: node 3 <---------------+
==================================== |
head: reference to ---------------+
first: node 3
rest: NULL
6) Since rest is NULL we just return and the stack is back to this:
====================================
head: reference to original head
first: node 1
rest: node 2 <---------------+
==================================== |
head: reference to ---------------+
first: node 2
rest: node 3
7) Now, the statement first->next->next = first; will cause the next part of node 3 to point to node 2 and the Linked List will become 1 -> 2 <- 3. The next part of node 2 will contain NULL. Since head is a reference to rest in the calling function then head = rest will make the rest referenced by head to point to the same node as the local rest:
====================================
head: reference to original head
first: node 1
rest: node 3 <---------------+ (head = rest; made *this* rest
==================================== | be equal to the *local* rest)
head: reference to ---------------+
first: node 2
rest: node 3
8) After that, we return and first will again point to node 1 and the statement first->next->next = first; will cause the next part of node 2 to point to node 1 and the Linked List will become 1 <- 2 <- 3. The next part of the node 1 will contain NULL and the statement head = rest will cause the pointer referenced by head to point to node 3 since rest was changed to point to node 3 in step 7.
We beginners should help each other.:)
In my opinion it is not easy to understand how the function works for such beginners as we.
So it is better to figure out its work using schemes.
If the list either does not contain nodes or contains only one node then there is nothing to reverse.
This code snippet corresponds to this conclusion.
/* checking for an empty list */
if (head == NULL)
return;
first = head;
rest = first->next;
/* List has only one node */
if (rest == NULL)
return;
Now let's assume that the list contains exactly two nodes. In this case it looks like
-------- ---------- ----------------
| head | -> | A |B| -> | B |nullptr|
-------- ---------- ----------------
This list is split into the following parts the following way
-------- ----------
| head | -> | A |B|
-------- ----------
-------- ----------
| first| -> | A |B|
-------- ----------
-------- ----------------
| rest | -> | B |nullptr|
-------- ----------------
This code snippet corresponds to this conclusion
first = head;
rest = first->next;
Now the function calls itself recursively
recursiveReverse(rest);
In fact it is called for this new list
-------- ----------------
| rest | -> | B |nullptr|
-------- ----------------
as this new list contains only one node then the function just returns.
As the original list must be reversed then the head must contain the value of rest that is the head must point to the node "B"
This code snippet corresponds to this conclusion
head = rest;
However in this case we will get
-------- ----------------
| head | -> | B |nullptr|
-------- ----------------
But this list contains only one node "B". So before executing this statement
head = rest;
we need to append the list with the node "A".
As we have that the pointer first points to the node "A"
-------- ----------
| first| -> | A |B|
-------- ----------
then we can do the following
first->next->next = first;
that results in
-------- ---------- -----------
| first | -> | A |B| -> | B | A|
-------- ---------- -----------
that is on the other hand we have
-------- ---------- -----------
| rest | -> | B |A| -> | A | B|
-------- ---------- -----------
and then after this statement
first->next = NULL;
we will get
-------- ---------------- | -----------
| first | -> | A |nullptr| | | B | A|-----------
-------- ---------------- | ----------- |
^ V
-------- | -----------------
| rest | ---------------------------- | A | nullptr|
-------- -----------------
Now it is indeed time to call the statement
head = rest;
and we will get
-------- ---------------- | -----------
| first | -> | A |nullptr| | | B | A|-----------
-------- ---------------- | ----------- |
^ V
-------- | -----------------
| head | ---------------------------- | A | nullptr|
-------- -----------------
That is the list is reversed.
If the list contains more than two nodes then after splitting the original list the pointer first will point to the first node of the original list that has to be the last node in the reversed list. In turn this first node will point to the next node that in the reversed list will be the last node.
Using this code snippet
first->next->next = first;
first->next = NULL;
we can place it after the last node in the reversed list. And all we need to do is to set the head to the value stored in the pointer rest because the pointer rest is the head of the reversed list to which the node pointed to by the pointer first is appended.
head = rest;
That is all.
Here is a demonstrative program
#include <iostream>
struct node
{
int value;
node *next;
};
void push( node * &head, int value )
{
head = new node { value, head };
}
std::ostream & out( node * const &head, std::ostream &os = std::cout )
{
for ( node *current = head; current != nullptr; current = current->next )
{
os << current->value << ' ';
}
return os;
}
void recursiveReverse( node * &head )
{
if ( head != nullptr && head->next != nullptr )
{
node *first = head;
node *rest = head->next;
recursiveReverse( rest );
first->next->next = first;
first->next = nullptr;
head = rest;
}
}
int main()
{
node *head = nullptr;
const int N = 10;
for ( int value = 0; value < N; value++ )
{
push( head, value );
}
out( head ) << std::endl;
recursiveReverse( head );
out( head ) << std::endl;
return 0;
}
Its output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9

Why this code for removing nodes from linked list doesn't work?

I am working on a question on Leetcode, which aims to remove linked list elements.
Here's the question:
Remove Linked List Elements
Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5
And here's my code:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* cur = head;
while(cur -> next != NULL && cur -> next -> val != val)
{
cur = cur -> next;
}
cur -> val = cur -> next -> val;
cur -> next = cur -> next -> next;
return head;
}
};
I bumped into a runtime error when I submitted the code. The question is really simple, but since I am not so familiar with C++, I still can't find out where the error is. Could you help me with that?
Your code crashes because the loop has two exit conditions:
You found the node that you were looking for, and
You reached the end of the list without finding the node
Your code assumes it's the first, not second condition, so it dereferences cur->next->val which may lead to a crash.
There are other problems with your code:
You need to handle deletion of multiple items, as shown in the example
You need to prevent memory leaks by freeing deleted nodes
You need to process a situation when head points to the node that must be deleted
You need to process a situation when the list is empty.

Recursive Reverse List

I need to write an algorithm called reverseNodes that takes a RefToNode as a parameter and recuriveley reverses the list the header i came up with was
Algorithm reverse (rList)
reverves elementsin a list
Pre: rList :: a referance to a list to be reversed
Post: elements in rList are reversed
if ( rList !=NULL)
reverseNodes (rList -> head)
return
I need to find a way to write this is psuedocode and find the time complexity
Sometimes it is easier to create some un-formal algorithm gibberish, if you start
with the idea expressed clearly. Then, obfuscate and verbalize until you have something, your professor will happily accept.
So, lets start with our general idea of the algorithm:
let rec fold folder acc l =
match l with
| [] -> acc
| x::xs -> fold folder (folder acc x) xs
let prepend l e = e :: l
let revlist l = fold prepend [] l
...and start to verbalize:
let result = empty list
let l = the list we want to reverse
if l is the empty list, goto 7
let head = l.front, l = l.pop_front()
result.push_front head
goto 3
l = result
The steps 3..6 can be easily expressed as a recursive function:
void loop(list& l, list& result)
{
if( l.is_empty()) return;
auto head = l.front();
l.pop_front();
result.push_front(head);
loop(l,result);
}
As we want to create the illusion of in-place.reversal, our reverse_list function is
void reverse_list( list& l )
{
list result;
loop( l, result);
l = result;
}
Alternate solution
We can also do it in another way:
let rec revlist1 l =
match l with
| [] -> l
| x::xs -> (revlist1 xs) # [x]
This basically states, that the reversed list is the front element of the original list appended to the reverse of the rest.
Translating the algorithm to gibberish form yields:
Node* reverse_list1( Node* list )
{
if( list == NULL) return NULL; // reverse of empty list is empty list.
if( list->next == NULL ) // last element in list?
return list; // the reverse of a list with 1 element is the same.
else
{
Node* head = list;
Node* tail = list->next;
head->next = NULL;
Node* end_of_reverse_tail = tail; // the first will be the last...
Node * result = reverse_list1(tail);
end_of_reverse_tail->next = head;
return result;
}
}
Note, that this is not a tail recursive solution.