I was trying the reversal of a linked list using recursion. I viewed the sample program in geeksforgeeks website. They had a good explanation. But I could not understand what the *headref will hold on every stack unwinding. Doesnt it hold the next address during every stack unwinding, if its that way then how does the rest value is same during all the stack unwinding calls. The first value gets changed during the stack unwinding and so is the rest value. Why doesnt rest value is not changed when the first value is changed for every stack unwinding. Please help to understand.
void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest;
/* empty list */
if (*head_ref == NULL)
return;
/* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next;
/* List has only one node */
if (rest == NULL)
return;
/* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first;
/* tricky step -- see the diagram */
first->next = NULL;
/* fix the head pointer */
*head_ref = rest;
}
Once the 'rest list' got reversed in the recursive step, its first item, pointed at by rest, became its last item, so the previous 'first' gets appended after that. Then it is the last item, so its next member becomes NULL. Finally we return the new head through the call parameter.
The head is changed in every recursive call.
Each recursive call takes the sublist [k,n] , where k is the previously parsed elements.
The first entry is [0,n] , which in the code above is [first,rest] .
Initially links are from first to rest.
Before each recursive call rest gets linked to first having a temporary loop inside the list (first points to rest, rest points to first).
Then , after the recursive call returns, the loop is killed by removing the first to rest link and putting first to be rest's next . (basically keeping only the inverse order).
As any single linked list, the last element needs to have no childern, and right now first is the last element, so first->next becomes null.
The new head of the list is the last element, which in this case will be rest , which gets passed on from the deepest recursion upwards.
This algorithm is so much faster and easier to implement with an iterative approach.
Problem of such algorithm is memory consumption required by recursive calls.
You have one parameter pointer and two var pointer, each call that goes on top of the memory stack. But it is the reason it works and the var is not changed. It does not reference the same memory area.
You can note that an iterative approch is faster and easier in fact.
void iterativeReverse(struct node** head_ref) {
struct node *prev=NULL, *next;
while (*head_ref) {
next=*head_ref->next;
*head_ref->next=prev;
prev=*head_ref;
*head_ref=next;
}
*head_ref=prev;
}
Related
I have a list inside a structure,
struct A{
list B;
};
I also have a pointer to this structure like
struct A *a;
Now, assume the list is already implemented, and its elements are of type elem.
Then, I do the following -
(i) I get the head of the list in nodeL (a pointer of elem type)
elem * nodeL = list_get_head(&(a->B));
(ii) I now loop through the list in this way:
while(nodeL != (elem *)(&a->B)){ // did not get this part ----- I
; //some code here
nodeL = list_get_next(&(a->B), nodeL);
}
Assume that list_get_head gets the pointer to head of list, and list_get_next gets the pointer to next element of passed second argument elem, of list.
Now my question is:
What is my loop condition here? Till what of list do I hope to loop? (see I) In other words, if &(a->B) is the address of the start of the list, what is &a->B here?
I thought this should loop till end of list, but it doesn't seem like that's what the while loop condition is doing. Also, this is a circular doubly linked list.
elem* x = list_get_head(&a->B);
elem* y = (elem *)(&a->B);
First at all, how far do x and y differ in your case?
To be valid at all, first member of list must be of type elem* anyway. I personally would assume that this is the head of the list, but then your while loop won't ever be entered, so it must rather be the tail??? But then your first element considered in the loop is the tail...
How is an empty list represented? Null pointer? If so, this is not covered by your code.
while(nodeL != (elem *)(&a->B))
did not get this part
Idea is simple: we start iterating at the head, and as long as the head is not reached again, we are still in the loop... Problem is, though, you have to distinguish two situations:
current node is head at start of the loop
current node is head after all elements have been iterated
I recommend different handling for iterating now:
elem* nodeL = list_get_head(&a->B);
if(nodeL) // based on assumption(!): otherwise, empty list
{
do
{
//some code here
nodeL = list_get_next(&a->B, nodeL);
}
while(nodeL != list_get_head(&a->B));
}
One element is guaranteed to be in the list, so we can use it unconditionally (thus a do-while loop). Then we iterate to the next element, until we reach the beginning again. I replaced the suspicious cast by another call to list_get_head, making the whole matter safer (not relying on assumptions any more either).
It is not clear if you are talking about std::list. But since you are mentioning unfamiliar list_get_head and list_get_next, I assume this is a non standard implementation.
So the guess is: In a list head is also an element. The condition while(nodeL != (elem *)(&A->B)) looks like it is checking when loop traverses back to the head of the circular list.
However, there are two observations:
Elements of a list are generally allocated from heap or a memory pool. Hence, if B is head, it should have been a pointer. Unless it is typedef elem * list.
The loop may not run because nodeL is already at head.
Suppose you have a variable and a pointer of the structure:
A var;
A* pntr;
Now to access a data member of the structure we do the following :
var.B // For a variable use dot
(*pntr).B or pntr->B //For a pointer we can use * . or ->
In your code while(nodeL != (elem *)(&a->B)) iterates over the list till the head of the circular list is encountered again.
We can get head by :
A* a;
//SOME INITIAL CODE
A* pntr;
pntr = a;
head = (elem*)&(pntr->B)
So look at the look like:
while( nodeL != (elem *) ( & ( a->B ) ) )
So I was going through a textbook example of how to make a queue from a linked list in C and I'm kinda of stuck on how exactly a piece of codes works.
So the example the textbook uses is a queue that helps models passengers waiting in line to be served by a ticket agent.
They start off by defining the structure of how the queue will be implemented:
/* Insert typedef for queue_element_t */
typedef struct queue_node_s {
queue_element_t element;
struct queue_node_s *restp;
} queue_node_t;
typedef struct {
queue_node_t *frontp,
*rearp;
int size;
} queue_t;
Then they go on to show the implementation of two functions:
void add_to_q(queue_t *qp, queue_element_t ele);
queue_element_t remove_from_q(queue_t *qp);
The first function is defined as:
/*
* Adds ele at the end of queue accessed through qp
* Pre: queue is not empty
*/
void
add_to_q(queue_t *qp, /* input/output - queue */
queue_element_t ele) /* input - element to add */
{
if (qp->size == 0) { /* adds to empty queue */
qp->rearp = (queue_node_t *)malloc(sizeof (queue_node_t));
qp->frontp = qp->rearp;
} else { /* adds to non-empty queue */
qp->rearp->restp =
(queue_node_t *)malloc(sizeof (queue_node_t));
qp->rearp = qp->rearp->restp;
}
qp->rearp->element = ele; /* defines newly added node */
qp->rearp->restp = NULL;
++(qp->size);
}
Similarly remove_from_q is implemented in the following way:
/*
* Removes and frees first node of queue, returning value stored there.
* Pre: queue is not empty
*/
queue_element_t
remove_from_q(queue_t *qp) /* input/output - queue */
{
queue_node_t *to_freep; /* pointer to node removed */
queue_element_t ans; /* initial queue value which is to
be returned */
to_freep = qp->frontp; /* saves pointer to node being
deleted */
ans = to_freep->element; /* retrieves value to return */
qp->frontp = to_freep->restp; /* deletes first node */
free(to_freep); /* deallocates space */
--(qp->size);
if (qp->size == 0) /* queue's ONLY node was deleted */
qp->rearp = NULL;
return (ans);
}
When I go through it by myself, I find that I am still somewhat confused as to why it works this way? Correct me if I'm wrong here: On the first call to the function add_to_q, we assume that the queue is initially empty so the queue_node_t pointers frontp and rearp both point to the same spot in memory allocated in heap. Thus as a result, frontp->restp == rearp->restp, which is why you are allowed to write the line
qp->frontp = to_freep->restp;
in remove_from_q? Plus, on the second call to add_to_q, when you add a second element frontp points to the same memory locate but rear moves to a new location?
My follow up to that would be that once one element is in the queue, if we go and add a new member to the back of the queue, how does the following block of code give us the correct functionality that we expect of our queue?:
else { /* adds to non-empty queue */
qp->rearp->restp =
(queue_node_t *)malloc(sizeof (queue_node_t));
qp->rearp = qp->rearp->restp;
}
qp->rearp->element = ele; /* defines newly added node */
qp->rearp->restp = NULL;
++(qp->size);
}
I've tried drawing this out in terms of memory blocks, but I don't see how once the program gets to the line qp->rearp = qp->rearp->restp;, when you write qp->rearp->restp = NULL; it doesn't also set qp->rearp equal to NULL as well since they should (to my knowledge) be pointing to the same spot in memory.
Any guidance would be greatly appreciated!!!
Thanks :)
let's have some brief overview :
Queue is a linear data structure, in which the first element is inserted from one end called REAR, and the deletion of exisiting element takes place from the other end called as FRONT.
KeyPoint: The process to add an element into queue is called Enqueue(insertion) and the process of removal of an element from queue is called Dequeue(deletion).
Now, I've created two design to let you understand the basic concept of insertion and deletion.
1. Insertion( also creation)
2. Deletion in Queue :
I hope you will understand the basic concept of queue using linked-list so that, you do not confused in future and can learn further.
A queue is a first in first out structure (I guess you already know that). This particular code implements it using a linked list. What it basically does is whenever you "enqueue" some data you add it at the rear end of the linked list (the tail). Thus, rear gets modified on every call of add_to_q.
My follow up to that would be that once one element is in the queue, if we go and add a new member to the back of the queue, how does the following block of code give us the correct functionality that we expect of our queue?:
qp->rearp points to the last node (the rear of the code). qp->rearp->restp is the so called "next" pointer of that node. qp->rearp->restp=malloc... makes a new node at the "next" of the old rear. qp->rearp=qp->rearp->restp makes qp->rearp point to the new rear. qp->rearp->restp makes the "next" of the last node NULL.
So the code basically adds new nodes at the tail end of the linked list and removes nodes from the head end (the other way around should be more efficient). They are using the word "rearp" because you are supposed to go stand at the "rear" of a queue.
This is basically dealing with a linked list while keeping a "tail" pointer as well as a "head" pointer for efficiency purposes.
I'd suggest drawing it out again (and again), with blocks and pointers. First, make sure you understand a simple linked list that uses only a head and next pointers. Then progress to this one that maintains the head, tail and size info. Your comments actually sound like you mostly got it, right down until your last comment about setting the last elements next pointer to NULL. (Hint: qp->rearp is now our last node, we put the element in it, and set it's 'next' pointer to NULL)
I was searching on how can I print a reverse of linked list and I found this piece of code
/* Function to reverse the linked list */
void printReverse(struct node* head)
{
// Base case
if (head == NULL)
return;
// print the list after head node
printReverse(head->next);
// After everything else is printed, print head
printf("%d ", head->data);
}
The problem is that I do not understand the part where it reaches the last pointer which points to NULL and how it comes back one by one and prints the linked list in reverse order.
Is the return statement what makes it go step by step back? Or something else? Please help because I do not understand.
This is a recursive function. Recursive functions work by pushing variables onto the execution stack. The execution order pops off the stack in reverse order from the order it was pushed on the stack. This means that the last execution prints first, then the one previous to that, and so forth until all executions of printReverse print their values.
This is a recursive function; that is to say, it calls itself.
Let's use the sequence example as your example data:
When you first run the function, it's pointing at the head, and the head is the item containing the data e. It has a next property, which is the item containing the data x. Therefore, head == NULL evaluates False and the if statement doesn't fire.
The function then calls a second copy of itself, pointing to the next item in the list - the item containing x. This has a next property, which is the item containing a. The function then calls a third copy of itself with this item, and so on and so forth until it hits the final e, and calls a copy of itself with the next property of that item - that is to say, it calls itself with NULL as the input.
This copy of the function then returns due to the if statement- crucially, it returns to the function that called it, in this case the copy of itself the level above. This copy then carries on where it left off, executing printf("%d ", head->data); - in this case, it prints an e. Then it falls out of the body of the function and so returns to the function that called it. This copy of the function will have a head->data value of l, and this will print as above. As such, it then runs through back up the chain until it gets to the original function call, prints the first e, and then returns to the function that called it.
Hope this makes sense, I know it's not the best or most elegant explanation of recursion but there's a lot of material out there if this is confusing explaining exactly how recursion works and how useful it can be!
The thing that makes it go in reverse is to have the printf() call after the recursive call to itself.
You can try interchanging the two calls as in
void printNormal(struct node* head)
{
// Base case
if (head == NULL)
return;
// Before all, we print this node info.
printf("%d ", head->data);
// print the rest of the list after this node
printReverse(head->next);
}
And you'll get the forward printing of the list.
The mission of the so commented Base case is to avoid infinite recursion. The end of the list is special, we can do the check on entering the printReverse() function, so we can deal with the special case of an empty list, or we have to do it at each call (then we should put a check before calling the function inside it, and in the code that calls the recursive function (better to put it at the beginning).
As others have already explained the recursive version. I suggest you to have a look at this iterative version of printing linked list in reverse order. This is more easy to understand and implement as compared to recursive version, however it increases time complexity.
// To ease testing of code here linked list is created randomly of given size.
#include<stdio.h>
#include<cstdlib>
#include<time.h>
#define size 10 //Size of list
struct node
{
int info;
struct node * next;
};
typedef struct node* Node;
Node start;
int main()
{
int i;
srand(time(NULL));
for(i=0;i<size;i++)
{
Node ptr;
ptr=(Node)malloc(sizeof(node));
ptr->info=rand()%100; //random list is created of given size.
ptr->next=NULL;
if(start==NULL)
start=ptr;
else
{
ptr->next=start;
start=ptr;
}
}
printf(" Traversal of Linked List in forward direction -\n");
Node temp=start;
while(temp!=NULL)
{
printf(" %d ",temp->info);
temp=temp->next;
}
printf("\n Traversal of Linked List in backward direction -\n");
Node ptr=NULL;
while(ptr!=start)
{
temp=start;
while(temp->next!=ptr)
temp=temp->next;
printf(" %d ",temp->info);
ptr=temp;
}
return 0;
}
For more details visit-
https://github.com/SahdevKansal02/Data-Structures-And-Algorithms.git
Jim Rodgers hits the nail on the head. However, you could make life very easy for yourself by having a doubly linked list.
So for example your entry (node) has both a previous and next member pointing to the previous entry and next entry respectively. Then you don't need more "obfuscated" code than necessary.
So i'm writing this function that makes the smallest node at the end of the linked list. So Far it works except for the last element. if the linked list is created as nodes containing items from 0~9, the list after this function is {1,2,3,4,5,6,7,8,0,9} and the zero does not become at the end.
Any ideas why?
my function;
int connecting(linkk A)
{
linkk L = A;
for (int i = 0; i<sizeof(L);i++)
{
if (L->item < L->next->item)
{
int a = L->item;
L->item = L->next->item;
L->next->item = a;
L = L->next;
}
else{L=L->next;}
}
return 0;
}
Let's start with what I think you should be doing differently:
The name of your function is connecting. Given the description of what you'd like the function to do, this is not a good name.
I can infer from the usage that linkk is a typedef'ed pointer. Hiding pointers this way is not a good idea, most of the time.
Your function returns an int. It's always 0. Why? This does not make any sense.
Because linkk is probably a pointer to a node, and you pass the head pointer by value (i.e. a copy of it) to the function, you're unable to handle the case where the head of your list is the minimum. Either return the "new" head pointer, or pass a pointer to the head pointer to be able to modify the head pointer.
Your use of sizeof is completely wrong, as already suggested. sizeof(L) will give you the size (in chars) of the pointer, thus probably 8 on a 64 bit system or 4 on a 32 bit system.
You're not changing the nodes, but rather moving the values in between the nodes. This is OK if it's what you want to do, but the description of your algorithm suggest that you want to move the node instead.
Your function is doing too much, IMO. This can be hard to split, but a better approach would be to separate finding / extracting the minimum and putting it at the end of the list.
You're modifying a lot more than you originally wanted to. Consider a list like 1, 2, 3, 0, 4. Using your algorithm, the list will be changed to 2, 3, 1, 4, 0. Doing this is not only bad for the performance, but also very surprising for the caller. Surprises aren't good when it comes to programming!
So, let's get to a hopefully good implementation, step by step:
struct node {
int item;
struct node * next;
};
I assume that you want to move the node containing the minimum value to the end of the list, as in your description. I'm also going to keep this into a single function receiving a struct node * head pointer, despite my point above, in order to keep closer to the original code. Let's get out the special / base cases first: Moving the minimum element of an empty list as well as of a single element list is trivial: Do nothing.
if (head == NULL || head->next == NULL) {
return head;
}
I'm returning the "new" head of the list to allow the caller to update it's own head pointer. (As already said, head is just a copy of the caller's head pointer, modifying it will not have any effect at the call site).
Because we're dealing with a singly linked list here, and the implementation should not unnecessarily iterate over the list, we should remember the node we've previously visited. Otherwise we couldn't easily extract a node from the list:
struct node * follow, * point;
follow follows directly behind the point.
Initially, we place the point to the second node of the list (we already checked that there are at least 2 nodes in the list). follow will thus point to the head:
point = head->next;
follow = head;
Since we want to find the minimum item, we need to keep track of the minimum of the already searched part of the list. We initialize it with the head node's value:
int currentMinimum = head->item;
Now we're ready to iterate over the list, in order to find the node containing the minimum. But we need not only find the node containing the minimum, but also the one before it and the one after it, in order to be able to extract it easily. So, 3 pointers:
struct node * predecessor, * minimum, * successor;
As we set the currentMinimum to heads item, we should also set the pointers accordingly:
predecessor = NULL; // Nothing preceding the head
minimum = head;
successor = head->next;
Now let's iterate, moving the point completely over the list, until it falls off at the end:
while (point != NULL) {
// to be continued
follow = point;
point = point->next;
}
// when we're here, follow will point to the last node
In each iteration, we need to check if we found a smaller value than the current minimum, and eventually remember the node containing it:
if (point->item < currentMinimum) {
predecessor = follow;
minimum = point;
successor = point->next;
currentMinimum = point->item;
}
Now, when we get out of the loop, the following state should be reached:
minimum points to the node containing the minimum.
follow points to the last node of the list.
The two above could be the same, which is a special case!
predecessor could still be NULL, which is another special case!
Considering first the special case of minimum = follow: In that case, the minimum is already at the end of the list, so profit! Otherwise, we need to "cut" the node at minimum out of the list and append it to the last node, pointed to by follow:
if (follow != minimum) {
if (predecessor != NULL) {
predecessor->next = successor; // Cut out
minimum->next = NULL; // will be the last node
follow->next = minimum; // append at end
} else {
// to be continued
}
}
As you can see, there's the second special case to consider: If predecessor is still NULL, then no item was smaller than heads item. (Therefore, we could also test for minimum == head) Thus, the first node of the list will be moved to the end. We need to inform the caller about this!
head = head->next; // Second node is now the first one, though this is not all we need to do, see further down!
minimum->next = NULL; // Will be the last node
follow->next = minimum; // Append at end
Since the assignment to head only changed the function parameter (which is a copy of the pointer with which the function has been called), we need to return the (possibly modified!) head pointer, giving the caller the ability to update its own head pointer:
return head;
A caller would thus use this function like so:
struct node * head = get_a_fancy_list();
head = move_minimum_to_end(head); // This is our function being called!
Finally, a thing to consider: As you can see, moving the node (instead of the item) is more complicated. We need to modify at least 2 pointers in order to achieve what we want. In contrast: Moving the item value requires two modifications of item values (and iterating is easier). Moving the node instead of the item thus makes only sense when pointer assignments are faster than item assignments. Since the items are of type int this is not the case here.
Moving the item instead of the node containing the item is considerably easier. First of all, we need to keep track of the minimum (value as well as node):
struct node * minimum;
int currentMinimum;
To iterate, we're again going to use two pointers. It can be done with a single one, but the code is going to be more readable this way:
struct node * point, * follow;
We start off with the same initial state:
minimum = head;
currentMinimum = head->item;
follow = head;
point = head->next;
Iterating is similar to the other implementation, as is the iteration step:
while (point != NULL) {
if (point->item < currentMinimum) {
minimum = point;
currentMinimum = point->item;
}
follow = point;
point = point->next;
}
// follow points to the last node now
Now, doing the same as the previous implementation, we can swap the items of the last node and the node with the minimum:
minimum->item = follow->item;
follow->item = currentMinimum; // contains minimum->item
There's no point in checking for follow != minimum like in the previous approach: You could do it, but swapping the item of a node with its own item won't do any harm. OTOH adding an if will add a branch, and thus a possible performance penalty.
Since we didn't change the list structure (the linking between nodes), there's not much more to consider. We don't even need to inform the caller about a new head, as there will never be any change to it. For style purposes, I'd add it either way:
return head;
Ok, this got a bit long now, but hopefully it's easy to understand!
Try this function
int connecting(linkk A)
{
linkk L = A;
while(L->next!=NULL)
{
if (L->item < L->next->item)
{
int a = L->item;
L->item = L->next->item;
L->next->item = a;
}
L=L->next;
}
return 0;
}
The iterative way of reversing a linked list is very easy way to do. I tried to understand the recursive way by going through the below link
http://www.geeksforgeeks.org/write-a-function-to-reverse-the-nodes-of-a-linked-list/
void recursiveReverse(struct node** head_ref)
{
struct node* first;
struct node* rest;
/* empty list */
if (*head_ref == NULL)
return;
/* suppose first = {1, 2, 3}, rest = {2, 3} */
first = *head_ref;
rest = first->next;
/* List has only one node */
if (rest == NULL)
return;
/* reverse the rest list and put the first element at the end */
recursiveReverse(&rest);
first->next->next = first;
/* tricky step -- see the diagram */
first->next = NULL;
/* fix the head pointer */
*head_ref = rest;
}
We first move the pointer to the tail of the linked list.
During stack unwinding we stitch the links reversely.
But for all the stack unwinding calls, *headref = rest . So as first is changing during the stack unwinding to the previous stack value, why doesnt the rest too didnt change. I created 4 nodes and viewed the values through the gdb. The rest values during stack unwinding remained constant but the first values are changing. Why is it rest not changing.
While thinking in terms of changing pointers and values is a good way
to think about iterative programs, it is a confusing way to look at
recursive programs, because each recursive call creates its own local
variables, all with the same names, but possibly different values.
With a recursive function it is more helpful to assume that it works correctly for input of size n, and then verify its correctness for input of size n+1. If the "base case" (size 0 or 1) is covered, this then proves that it works for all inputs
In your case, let's suppose that recursiveReverse works OK for lists of length 3, and let's feed it a list of length 4 a->b->c->d by
calling recursiveReverse(&p) where p=a
Both first->next and rest will be b, hence point to a 3-element list b -> c -> d, so (by our assumption)
recursiveReverse(&rest) will correctly reverse this list. After the
call, rest has changed value (from b to d) and now points to this reversed list d->c->b
first->next is still the same pointer b as before the call, and therefore now points to the end of the list.
Thus, first->next->next = first attaches first to the end of this reversed list, which then becomes d->c->b->a)
As first is now the end of the list, we now need first->next = NULL. The final step is to change *head_ref (from a to d), so, after returning from recursiveReverse(&p), p will have changed from a to the new head of the list, d.
This shows that whenever the function works correctly for n-element
lists, it works correctly for n+1-element lists. The base case is easy,
so whe have shown that it works for all lists.
Now, why don't you see rest changing value in your debugger? Because
its value is only ever changed by the function call
recursiveReverse(&rest). Before you recursively call
recursiveReverse it has one value, after you return from it it has
another, you don't see it changing when stepping in and out of each function call. The assignment that changes its value is actually the very last (*head_ref = rest) before the function returns, but the assignee is called head_ref in this stack frame, not rest (as it was called in the stack frame of the caller)
This is the "same names, but different values" confusion I mentioned above.