reverse linked list in C using recursion - c

I have written following code in C. I am pretty new to C. The insert and Print functions seem to work fine but I get a prompt that says program stopped working when I call Reverse function.
Where dis I go wrong ?
//WAP to reverse a Linked List using recursion
#include<stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node* next;
};
struct Node* head; //global variable
struct Node* Reverse(struct Node* p){
if(p->next == NULL){ //since for last node link part is null
head = p;
printf("break condition");
return head;
}
printf("calling reverse");
Reverse(p->next);
struct Node* q = p->next;
q->next = p;
p->next = NULL;
}
void Insert(int x){
struct Node* temp= (struct Node*)malloc(sizeof(struct Node));
temp->data = x;
//temp->next = NULL; //redundant
//if(head!= NULL){
temp->next = head; //temp.next will point to null when head is null nd otherwise what head was pointing to
//}
head = temp;
}
void Print(){
struct Node* temp1 = head; //we dont want tomodify head so store it in atemp. bariable and then traverse
while(temp1 != NULL){
printf(" %d", temp1->data);
temp1= temp1->next;
}
printf("\n");
}
int main(){
struct Node* head = NULL;
Insert(2);
Insert(4);
Insert(5);
Insert(1);
Print();
head = Reverse(head);
// Print();
}

There are two issues with the program above:
1) You have two head variables. One is a global variable, and the other is a variable local to the main function. That local variable is the one that is passed to Reverse(). Since the first thing that function does is dereferencing it, the program crashes. Removing the local head variable in the main() function should address it.
2) The Reverse() function correctly returns head when it reaches the exit condition, but what happens the rest of the time? It's missing a return in the non-exit condition case. Here's a diff that would address the issue:
printf("calling reverse");
- Reverse(p->next);
+ struct Node* ret;
+ ret = Reverse(p->next);
struct Node* q = p->next;
q->next = p;
p->next = NULL;
+ return ret;

Related

Printing doubly linked list in C goes into infinite loop

Im trying to learn doubly linked lists. I used the following to print:
typedef struct Node{
int data;
struct Node* prev;
struct Node* next;
}node;
typedef struct List{
node *head;
}list;
node * createNode(int data) {
node * newNode = (node*)malloc(sizeof(node));
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
_Bool isEmpty(const list *L)
{
if (L->head == NULL)
return 1;
return 0;
}
_Bool insert(list *L, node *N) {
if(isEmpty(L)) {
L->head = N;
}
else{
L->head->prev = N;
N->next = L->head;
L->head = N;
}
if (L->head==N)
return 1;
return 0;
}
void _print(list *L){
node *temp=L->head;
while(temp!=NULL){
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(int argc, char *argv[]){
list *L1=(list *)malloc(sizeof(list));
node *N1=createNode(3);
node *N2=createNode(1);
node *N3=createNode(5);
insert(L1, N3);
insert(L1, N2);
insert(L1, N1);
_print(L1);
}
for reference my list struct only contains a pointer "head" and my node struct contains next, prev and data.
It prints the correct data but goes into infinite loop.
What is the reason ?
The problem is that this line in main:
list *L1=(list *)malloc(sizeof(list));
Allocates memory for the list, but does not initialize it.
Without initialization the value of L1->head can be anything.
And if it happens to be different than 0 (i.e. NULL), insert will interpret it as pointing to a valid node (which it isn't).
The result is undefined behavior (UB), which means anything can happen. It might seem to work, it can crash, or get into an infinite loop etc.
In order to fix it, you need to initialize the list pointed by L1.
You can do it at least in 2 ways:
Replace the call to malloc with calloc, which also zeroes the allocated memory:
list* L1 = (list*)calloc(sizeof(list), 1);
Add an explicit initialization after the malloc:
list* L1 = (list*)malloc(sizeof(list));
L1->head = NULL; /* <--- initialization */
You can also add a function for encapsulating the initialization.

I'm having a problem creating a linked list [duplicate]

This question already has answers here:
Linked lists - single or double pointer to the head
(3 answers)
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 10 months ago.
#include<stdio.h>
#include<stdlib.h>
void insert_front(struct node* head, int block_number);
void insert_rear(struct node* head, int block_number);
void print_list(struct node* head);
struct node {
int block_number;
struct node* next;
};
int main(void)
{
struct node* list = NULL;
insert_front(list, 10);
insert_rear(list, 20);
insert_front(list, 30);
insert_rear(list, 40);
print_list(list);
return 0;
}
void insert_front(struct node* head, int block_number)
{
struct node* p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = head;
head = p;
return head;
}
void insert_rear(struct node* head, int block_number)
{
struct node* p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = NULL;
if (head == NULL) {
head = p;
}
else {
struct node* q = head;
while (q->next != NULL) {
q = q->next;
}
q->next = p;
}
}
void print_list(struct node* head)
{
struct node* p = head;
while (p != NULL) {
printf("--> %d ", p->block_number);
p = p->next;
}
printf("\n");
}
When I ran it, there was no result at all.
Now, in the insert_front function p->block_number = block_number, a message appears saying that the NULL pointer 'p' is being dereferenced... (The same thing appears in the insert_rear function.)
Could it be that I am declaring the pointer wrong?
Both insert_front and insert_rear need to convey possibly head modification back to the caller, and the caller needs to reap that information. Both should be declared to return struct node *, do so, and the code in main react accordingly. E.g.:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
struct node * insert_front(struct node *head, int block_number);
struct node * insert_rear(struct node *head, int block_number);
void print_list(struct node *head);
struct node
{
int block_number;
struct node *next;
};
int main(void)
{
struct node *list = NULL;
list = insert_front(list, 10);
list = insert_rear(list, 20);
list = insert_front(list, 30);
list = insert_rear(list, 40);
print_list(list);
return 0;
}
struct node *insert_front(struct node *head, int block_number)
{
struct node *p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = head;
head = p;
return head;
}
struct node *insert_rear(struct node *head, int block_number)
{
struct node *p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
struct node *q = head;
while (q->next != NULL)
{
q = q->next;
}
q->next = p;
}
return head;
}
void print_list(struct node *head)
{
struct node *p = head;
while (p != NULL)
{
printf("--> %d ", p->block_number);
p = p->next;
}
printf("\n");
}
Output
--> 30 --> 10 --> 20 --> 40
I leave the memory leaks for you to resolve.
In C all variables are passed by value – if you pass a pointer, then it is copied, too (not the pointed to object, of course...), and function parameters, apart from being initialised from outside, are nothing more than local variables. Thus via head = p; you just assign the local copy of the outside pointer, not the latter itself!
To fix that you have two options:
Return the new head and make the user responsible for re-assigning the returned value to his own head pointer.
Accept the head as pointer to pointer.
With second approach a user cannot forget to re-assign the (potentially) new head, so that's what I'd go with:
void insert_whichEver(node** head, int block_number)
{
// use `*head` where you had `head` before...
}
void demo()
{
node* head = NULL;
insert_front(&head, 1012);
}
And in insert_front drop return head;, a function with void cannot return anything concrete and does not require a return at all (but bare return; can be used to exit a function prematurely).

How to implement singly linked list in C

I am trying to populate my linked list in C, but id does not word how
I want to. I want to keep a pointer "p" and keep adding to the list with the same pointer. However when I try to print, it prints only the data of the head!
#include<stdio.h>
#include <stdlib.h>
typedef struct{
int data;
struct node *next;
}node;
int main(){
node *head = NULL;
head = malloc(sizeof(node));
if(head==NULL){
printf("ta foirer quelque chose frero!");
return 1;
}
(*head).data=3;
(*head).next=NULL;
node *p = NULL;
p = (node*) head->next;
p = malloc(sizeof(node));
p->data = 5;
p->next = NULL;
p= (node *)p->next;
int i=0;
while(i<5){
p = malloc(sizeof(node));
i++;
p->data = i;
p->next=NULL;
p= (node *)p->next;
}
p = head;
while(p){
printf("\n%d",p->data);
p =(node*) p->next;
}
return 0;
}
I am getting as output
3
and I am expecting to get
3
5
0
1
2
3
4
#include<stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
typedef struct Node node;
void insert(node* h, int v) {
node* tmp = h;
while(tmp->next)
tmp = tmp->next;
node* newnode = malloc(sizeof(node));
newnode->data = v;
newnode->next = NULL;
tmp->next = newnode;
}
int main(){
node *head = NULL;
head = malloc(sizeof(node));
if(head==NULL){
printf("ta foirer quelque chose frero!");
return 1;
}
head->data=3;
head->next = NULL;
node *p = NULL;
insert(head, 5);
int i=0;
while(i<5){
insert(head, i++);
}
p = head;
while(p){
printf("%d\n",p->data);
p = p->next;
}
return 0;
}
If you notice, I changed the layout of your code a bit, and made it cleaner. What you needed was to traverse to find the node that appears before the place to add the new node, which in this case is the end. Usually this is a separate pointer in a different struct that contains the head and this is called the tail of a linked list. You were simply not keeping track of where to really add the node. This insert function above does that.

Linked string list in c

I'm trying this simple code which asks a user for string input. As it receives an input it then tries to copy each element of the string into different location in a linked list. Everything works just fine (I think) but when i print the linked list, the screen doesnt show any out put. Any idea why is this happening?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct node {
char data;
struct node* next;
};
struct node* head = NULL;
void insert(char);
void print();
void main() {
char str1[20];
int i;
printf("Enter the string\n");
fgets(str1,20,stdin);
int len = strlen(str1);
printf("%d\n",len);
for(i=0;i<len;i++) {
insert(str1[i]);
}
print();
}
void insert(char str) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
struct node* temp1 = head;
while(temp1!=NULL) {
temp1 = temp1->next;
}
temp->data = str;
temp1 = temp;
}
void print() {
struct node *temp;
temp = head;
while(temp!=NULL) {
printf("%c ",temp->data);
temp = temp->next;
}
}
You never set head to anything, it will always be NULL. So, you're not creating a list, but a group of unlinked floating nodes.
On another note, don't cast the result of malloc
On yet another note, no need to go through the entire list for every insert - you can keep a tail pointer along with the head, so adding to the end is done without a loop.
void insert(char str) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = str;
temp->next = NULL;
if(head){//head != NULL
struct node* temp1 = head;
while(temp1->next != NULL) {//search last element
temp1 = temp1->next;
}
temp1->next = temp;//insert new node
} else {
head = temp;//if head == NULL then replace with new node
}
}

C: How to free nodes in the linked list?

How will I free the nodes allocated in another function?
struct node {
int data;
struct node* next;
};
struct node* buildList()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
return head;
}
I call the buildList function in the main()
int main()
{
struct node* h = buildList();
printf("The second element is %d\n", h->next->data);
return 0;
}
I want to free head, second and third variables.
Thanks.
Update:
int main()
{
struct node* h = buildList();
printf("The element is %d\n", h->next->data); //prints 2
//free(h->next->next);
//free(h->next);
free(h);
// struct node* h1 = buildList();
printf("The element is %d\n", h->next->data); //print 2 ?? why?
return 0;
}
Both prints 2. Shouldn't calling free(h) remove h. If so why is that h->next->data available, if h is free. Ofcourse the 'second' node is not freed. But since head is removed, it should be able to reference the next element. What's the mistake here?
An iterative function to free your list:
void freeList(struct node* head)
{
struct node* tmp;
while (head != NULL)
{
tmp = head;
head = head->next;
free(tmp);
}
}
What the function is doing is the follow:
check if head is NULL, if yes the list is empty and we just return
Save the head in a tmp variable, and make head point to the next node on your list (this is done in head = head->next
Now we can safely free(tmp) variable, and head just points to the rest of the list, go back to step 1
Simply by iterating over the list:
struct node *n = head;
while(n){
struct node *n1 = n;
n = n->next;
free(n1);
}
One function can do the job,
void free_list(node *pHead)
{
node *pNode = pHead, *pNext;
while (NULL != pNode)
{
pNext = pNode->next;
free(pNode);
pNode = pNext;
}
}
struct node{
int position;
char name[30];
struct node * next;
};
void free_list(node * list){
node* next_node;
printf("\n\n Freeing List: \n");
while(list != NULL)
{
next_node = list->next;
printf("clear mem for: %s",list->name);
free(list);
list = next_node;
printf("->");
}
}
You could always do it recursively like so:
void freeList(struct node* currentNode)
{
if(currentNode->next) freeList(currentNode->next);
free(currentNode);
}

Resources