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.
Related
I tried to do insertion in linked list by passing it to a function using pointer to pointer call(call by reference). I tried using a different variable for head pointer within the function, but insertion doesn't takes place due to use of that variable at some places (as mentioned in the code below). If i use *head in place of hd at the below mentioned position the code runs successfully.
Why this problem arises?
**EXPLAINED MY PROBLEM AND QUESTION IN THE CODE BELOW**
typedef struct ll {
int data;
struct ll *next;
}list;
**insert(&head,&n); this is used in main() for insertion**
**FUNCTION FOR INSERTION IN LINKED LIST**
void insert(list **head,int *n) **n=size of linked list**
{
list *hd;
hd=*head; **i am trying to use this variable for convenience**
int pos,i,value;
list *ins,*t;
printf("\nenter position to insert ");
scanf("%d",&pos);
if(pos>(*n+1) || pos<1)
{
printf("\ninvalid position\n");
return;
}
printf("enter value to insert ");
scanf("%d",&value);
ins=(list*) malloc(sizeof(list));
ins->data=value;
if(pos==1)
{
ins->next=hd; **hd can be used here**
*head=ins; ***this is the problem postion***
**if i use hd=ins here then no insertion takes place,why?**
**but if i use *head=ins as used then code runs successfully.**
}
else
{
for(i=1;i<pos-1;i++) **BUT IN THIS BLOCK ALSO ,I CAN USE hd i.e. not neccessary to use *head **
{
hd=(hd->next);
}
t=hd;
hd=(hd->next);
t->next=ins;
ins->next=hd;
}
*n=*n+1;
}
I think, your "list" in "insert" is exist in "insert" only and drops after exiting from it. It needed or copy the added structure in already existing sequence and correct the pointers or provide empty place in the array with sequence or ti increase this array before inserting and in any case correct pointers. And I prefer two-relation list.
This is my program to sort a linked list by Bubble sort. When I use while it is OK, but when I use for loop it have an infinite loop so my program is stop unexpectedly. On the other hand, for the first swap of first and second element, I change pointer head point to the second but maybe it doesn't work for the whole program.
For example,
Ex1:
Input : 3,2,4,1,5
Output: 2,3,4,5
Ex2:
Input: 4,3,2,1,5
Output:3,4,5
Ex3:
Input: 3,2,1
Output: 2,3
I think that it just change the address the head pointer point to for the first time, so head is point to 2 in Ex1, 3 in Ex2 and 2 in Ex3.
void Swap(Node *p1, Node *p2)
{
Node *t;
t=p2->next;
p2->next=p1;
p1->next=t;
}
Node *BubbleSort(Node *head,int n) //pass the address of the first element in linked list and the linked list size
{
Node *tmp=head;
int swap=1;
for(int i=0;i<n-1;i++)
{
tmp=a; swap=0;
for(int j=0;j<n-1;j++)
{
if((tmp->data)>(tmp->next->data))
{
if(j==0) //if this is the first and second element I will change the address of the pointer
a=tmp->next;
Swap(tmp,tmp->next);
swap=1;
}
else tmp=tmp->next; //If the element I focus on is not greater than its folowing I will move the tmp pointer to the next.
}
if(swap==0)
return head;
}
return head;
}
int main()
{
Node*head;
//Assume I have a linked list with n elements
head=BubbleSort(head,n);
}
I searched for an other way in GeekforGeek but I still want to know why my code doesn't work. I have think for almost a long day. Please help me !
The Swap function is off by one. Therefore, in the innermost loop body you need to Swap(tmp->prev, tmp) instead of Swap(tmp, tmp->next).
You need to compare and swap the same elements, not compare the current and next element but swap the next and 2nd next element.
if( (tmp->data) > (tmp->next->data) ), then tmp->prev->next should point to tmp->next and tmp->next->next should point to tmp.
However, there is one thing to take care of: As you Swap(tmp->prev, tmp) you need to start one element further, too. This is also clear from the fact that the head points to the first element but does not contain any data. first->prev should point to the head, the head should be rw.
It's possible to let the top level code maintain the head but it's better if the ll code maintains it's own head.
I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.
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;
}
I wrote an implementation of linked lists (with two points, one for the next value, and one for the previous value) in C language and I'm trying to test my code.
I checked that it scans and prints correctly, however, when I try to test the code I wrote to find a value in list, it returns incorrect output.
The code for find in list is:
node* find_in_list(node *anchor,data_type x)
{
node *temp;
int is_empty=0;
is_empty=is_list_empty(anchor);
if(is_empty)
return NULL;
temp=anchor->next;
while(temp!=NULL)
{
if(temp->data==x)
return temp;
temp=temp->next;
}
return temp;
}
The code to check if the list is empty is
int is_list_empty(node *anchor)
{
int boolean=0;
if(anchor->next=NULL)
boolean=1;
return boolean;
}
It should be noted that anchor never changes. I define anchor as a node in the linked list that does not have an actual value, instead I just use it as a pointer to the first "real" node.
The void main is
#include "linked_list.h"
void main()
{
data_type num;
node *anchor;
anchor=create_node();
scan_list(anchor);
printf("The list scanned is \n");
print_list(anchor);
printf("Enter the number you wish to find\n");
scanf("%d",&num);
printf("The address of %d is\n",num);
printf("%p",find_in_list(anchor,num));
getch();
}
The scanning and printing are done properly. It does indeed print the correct list, but when I try to print the address of some value in the list (no matter what value I enter) it returns 000000.
What is the problem?
I know you've already solved your problem, but ultimately a more straight forward algorithm may have prevented your issue in the first place.
From an elegance/beautiful/simplicity point-of-view, I'd re-write find_in_list() to be something like the following, after eliminating the is_list_empty() routine:
node* find_in_list(node *list,data_type x)
{
for(;list;list=list->next)
if(list->data==x)
break;
return list;
}
(edited to use for-loop)