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 -|
Related
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.
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
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.
I want to write a method that merges two lists together in an alternating manner. So if I have list1=(0,1,2,3,4) and list2=(5,6,7,8), then the final list should be (0,5,1,6,2,7,3,8,4). Do you any ideas or hints, because I've tried so many things, but all fail to make sense.
That's pretty trivial if you don't need to keep the original lists intact.
algorithm would look like something like that:
start from the head of list 1, go to item 1 (1.1)
pick the corresponding item (2.1) from the list 2, change its head to the list 1 head, its prev to list 1 current item (1.1), change the current item next pointer to 2.1, and change 1' next pointer to point to 1.2. Make sure that 1.2 prev points to 2.1 now.
Move to 1.2 and 2.2 on each list, and repeat, until the end.
// I've been doing Java for a few years now, so my pointers are a bit rusty...
// Forgive pointer errors and focus on concept
/**
* #Param list1 the pointer to the head of the first list
* #Param list2 the pointer to the head of the second list
* Assumption - list 1 will be able to swallow list 2 without overflowing
* handling that is left to OP
*/
void mergeInto(Node *list1, Node *list2) {
Node curr1 = list1;
Node curr2 = list2;
while(curr2 != null) {
// store after nodes
Node after1 = curr1.next;
Node after2 = curr2.next;
// link curr2 into list1
curr1.next = curr2;
curr2.prev = curr1;
after1.prev = curr2;
curr2.next = after1;
// move on to the next in list2
curr2 = after2;
}
}
For starters this is apart of my current homework assignment for my Data Structures class. I am not asking for answers, I am asking for help.
I have a stack class that is implementing a Linked List instead of an array. I am currently trying to write my pop() function. I have a node for my theBack part of the stack.
I am just confused as to getting to the predecesor of my theBack node.
Any help with this would be awesome! Thanks!
A stack is actually reasonably simple to implement as a singly linked list, due to its restricted push and pop operations. It's actually a lot easier if you insert pushed elements at the head of the list. Since it's homework, I'll provide pseudo-code.
To initialise a stack, it's simply creating:
top -> null
with this code:
def init (stk):
stk->top = null # just initialise to empty.
Pushing an item is actually inserting it at the start of the list. So, when you push 3, 4 and 5, you get:
+---+
top -> | 3 | -> null
+---+
+---+ +---+
top -> | 4 | -> | 3 | -> null
+---+ +---+
+---+ +---+ +---+
top -> | 5 | -> | 4 | -> | 3 | -> null
+---+ +---+ +---+
with the following code:
def push (stk, val):
item = new node # Create the node.
item->value = val # Insert value.
item->next = stk->top # Point it at current top.
stk->top = item # Change top pointer to point to it.
And popping is then just removing that first node.
def pop (stk):
if stk->top == null: # Catch stack empty error.
abort with "stack empty"
first = stk->top # Save it for freeing.
val = first->value # Get the value from the top.
stk->top = first->next # Set top to the top's next.
free first # Release the memory.
return val # Return the value.
Each node in the singly-linked list links to the previous node. The very first item pushed onto the stack has a NULL, all the others point to the item 'below' them (the predecessor) in the stack.
So before you destroy the top node, you grab the backlink and save it as the new top. Something like this pseudocode, which presumes a stack of int values:
pop()
ALink *poppedLink = myTop;
myTop = poppedLink.nextNode; // point to next node
int returnValue = poppedLink.value; // save the value
delete poppedLink; // destroy the instance
return returnValue;
If by "predecessor", you mean: "the thing that was popped before this": that's long gone, isn't it?
if you're implementing a stack, then you would want to pop the top node anyways, so you would set theTop to be the next node in line (which should be a pointer in theTop node)
What do you mean the "predecessor" of top? Top node is the head of your list, it doesn't have any predecessors.