I feel confusion in linked list.what is the solution? - c

Specially i feel confusion about passing the head in function.Would any one kindly explain?
#include<stdio.h>
struct node
{
int data;
struct node *next;
};
struct node *makeNode(int item)
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = item;
newNode->next = NULL;
return newNode;
}
void traverse(struct node *head)
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("%d ",ptr->data);
ptr = ptr->next;
}
printf("\n");
}
void push(struct node **headRef, int data)
{
struct node *newNode = makeNode(data);
newNode->next = *headRef;
*headRef = newNode;
}
void append(struct node **headRef, int data)
{
struct node *newNode = makeNode(data);
struct node *ptr = *headRef, *temp;
if( ptr == NULL )
{
*headRef = newNode;
return;
}
while(ptr != NULL)
{
temp = ptr;
ptr = ptr->next;
}
temp->next = newNode;
}
void deleteData(struct node **headRef, int key)
{
struct node *ptr = *headRef, *prevNode;
//If key is in head node
if( (ptr->data == key) && (ptr != NULL) )
{
*headRef = ptr->next;
free(ptr);
return;
}
while( (ptr != NULL) && (ptr->data!=key) )
{
prevNode = ptr;
ptr = ptr->next;
}
if(ptr == NULL)
printf("Underflow or Key not found.\n");
else
{
prevNode->next = ptr->next;
free(ptr);
}
}
int main()
{
struct node *head = NULL;
int data;
printf("Enter Positive Data:\n");
scanf("%d",&data);
while( data>=0 )
{
append(&head,data);
in this function , pass the address of head.
scanf("%d",&data);
}
printf("\nTraversing...\n");
traverse(head);
but in this function why i only pass the head?
printf("\n\nEnter a data to delete:\n");
scanf("%d",&data);
deleteData(&head,data);
printf("\nTraversing...\n");
traverse(head);
}

In Function traverse
void traverse(struct node *head) {
......
......
}
Traverse function has a parameter head which is of type struct node pointer.
Hence to call traverse function you must pass an argument of type struct node pointer.
In main function you defined head as struct node *head = NULL;
that's why you are making call to the function like traverse(head).
In Function append
void append(struct node **headRef, int data)
{
....
....
}
The argument headref is of type 'pointer to pointer'.
Pointer to Pointer variable stores the address of pointer
Hence, you must pass address of pointer as argument and you make call to append function as append(&head,data)
To use pointer as a parameter in append function
Change the return type of you function from void to struct node* and return the headRef pointer.
struct node* append(struct node *headRef, int data)
{
struct node *newNode = makeNode(data);
struct node *ptr = headRef, *temp;
if( ptr == NULL )
{
headRef = newNode;
return headRef;
}
while(ptr != NULL)
{
temp = ptr;
ptr = ptr->next;
}
temp->next = newNode;
return headref;
}
Inside the main function, you should call append function like this.
head = append(head,data); //since append function is now returning a pointer
Complete code to append nodes using single pointer
#include<stdio.h>
struct node
{
int data;
struct node * next;
};
struct node * makeNode(int item)
{
struct node * newNode = (struct node * ) malloc(sizeof(struct node));
newNode -> data = item;
newNode -> next = NULL;
return newNode;
}
void traverse(struct node * head)
{
struct node * ptr = head;
while (ptr != NULL)
{
printf("%d ", ptr -> data);
ptr = ptr -> next;
}
printf("\n");
}
struct node * append(struct node * headRef, int data)
{
struct node * newNode = makeNode(data);
struct node * ptr = headRef, * temp;
if (ptr == NULL)
{
headRef = newNode;
return headRef;
}
while (ptr != NULL)
{
temp = ptr;
ptr = ptr -> next;
}
temp -> next = newNode;
return headRef;
}
int main()
{
struct node * head = NULL;
int data;
printf("Enter Positive Data:\n");
scanf("%d", & data);
while (data >= 0)
{
head = append(head, data);
scanf("%d", & data);
}
printf("\nTraversing...\n");
traverse(head);
return 0;
}

Function append may alter the value of head (which is a pointer). The signature is therefore void append(struct node **headRef, int data); note the **, which denotes a pointer to a pointer. So you have to pass the address of the pointer in order to allow append to change the pointer, i.e. call append(&head,data).
Function traverse, in contrast, needs not to alter the value of head, so it consumes the pointer directly (and not a pointer to that pointer). The signature is therefore void traverse(struct node *head); note the single *. Hence, call it like traverse(head).

include
struct node
{
int data;
struct node *next;
};
struct node *makeNode(int item)
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = item;
newNode->next = NULL;
return newNode;
}
i got bug in the above line
void traverse(struct node *head)
{
struct node *ptr = head;
while(ptr != NULL)
{
printf("%d ",ptr->data);
ptr = ptr->next;
}
printf("\n");
}
i know that there is no need to return the pointer .is it true? if it is true why need to give a return type in the following function?
struct node* append(struct node *headRef, int data)
{
struct node *newNode = makeNode(data);
struct node *ptr = headRef, *temp;
if( ptr == NULL )
{
headRef = newNode;
return headRef;
}
while(ptr != NULL)
{
temp = ptr;
ptr = ptr->next;
}
temp->next = newNode;
return headref;
}
int main()
{
struct node *head = NULL;
int data;
printf("Enter Positive Data:\n");
scanf("%d",&data);
while( data>=0 )
{
head=append(head,data);
scanf("%d",&data);
}
printf("\nTraversing...\n");
traverse(head);
}

Related

Why is (null) being printed in my c code?

I am trying to add strings to a linked list but I have a problem with (null) being printed. Anyone who can help me?
The best I could do is narrow it down to this being the problem:
struct node *head = malloc(sizeof(struct node));
struct node *ptr = malloc(sizeof(struct node));
Here is the code:
#include <stdio.h>
#include <stdlib.h>
struct node {
char *data;
struct node *link;
};
struct node *add_begin(char *d, struct node *head) {
struct node *ptr = malloc(sizeof(struct node));
ptr->data = d;
ptr->link = head;
return ptr;
}
void add_end(struct node *point, char *data) {
struct node *temp = malloc(sizeof(struct node));
temp->data = data;
temp->link = NULL;
while (point->link != NULL) {
point = point->link;
}
point->link = temp;
}
int main() {
struct node *head = malloc(sizeof(struct node));
struct node *ptr = malloc(sizeof(struct node));
head->link = ptr;
char *data = "Chocolate Cake";
head = add_begin(data, head);
add_end(ptr, data);
while (head != NULL) {
printf("%s \n", head->data);
head = head->link;
}
}
Output:
Chocolate Cake
(null)
(null)
Chocolate Cake
The problem is you allocate dummy nodes, which are uninitialized and happen to have null pointers as data and link. The list should be initially empty, ie: head should be a null pointer.
Note that add_end should also return the head pointer in case an empty list was passed. Passing the arguments in the same order to both functions is highly recommended.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct node {
char *data;
struct node *link;
};
struct node *add_begin(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = head;
return ptr;
}
struct node *add_end(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = NULL;
if (head == NULL) {
return ptr;
} else {
struct node *temp = head;
while (temp->link != NULL) {
temp = temp->link;
}
temp->link = ptr;
return head;
}
}
int main() {
struct node *head = NULL;
char *data = "Chocolate Cake";
head = add_begin(head, data);
head = add_end(head, data);
for (struct node *ptr = head; ptr; ptr = ptr->link) {
printf("%s\n", ptr->data);
}
return 0;
}
Output:
Chocolate Cake
Chocolate Cake

Element deletion in single linked list at head not working

#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head = NULL;
struct node *second = NULL;
struct node *third = NULL;
void insertAtBeg(struct node *n, int data) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = data;
temp->next = head;
head = temp;
}
void insertAtEnd(struct node *n, int data) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = data;
temp->next = NULL;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
}
void deleteElement(struct node *head, int data) {
if (head->data == data) {
struct node *temp;
temp = head;
head = head->next;
free(temp);
printf("after deletion at head in function\n");
printList(head);
}
}
void printList(struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
void main() {
head = (struct node*)malloc(sizeof(struct node));
second = (struct node*)malloc(sizeof(struct node));
third = (struct node*)malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printList(head);
insertAtBeg(head, 0);
printf("after insertion at beginning\n");
printList(head);
insertAtEnd(head, 4);
printf("after insertion at End\n");
printList(head);
deleteElement(head, 0);
printf("after deletion at head in main\n");
printList(head);
}
output of the code is
1
2
3
after insertion at beginning
0
1
2
3
after insertion at End
0
1
2
3
4
after deletion at head in function
1
2
3
4
after deletion at head in main
0
1
2
3
4
Why is there a difference in output of the function called in main and the function called in another function.ie.after deletion at head in function and after deletion at head in main, when both are supposed to be deleting element from the same list
The problem is you need a way to modify the head of the list when inserting and/or deleting elements from the list.
A simple way to do this is for these functions to return a potentially updated value of the head pointer and for the caller to store this return value into it's head variable.
Here is a modified version of your code with these semantics:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insertAtBeg(struct node *head, int data) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
// should test for memory allocation failure
temp->data = data;
temp->next = head;
return temp;
}
struct node *insertAtEnd(struct node *head, int data) {
struct node *temp;
struct node *n;
temp = (struct node*)malloc(sizeof(struct node));
// should test for memory allocation failure
temp->data = data;
temp->next = NULL;
if (head == NULL)
return temp;
n = head;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
return head;
}
struct node *deleteElement(struct node *head, int data) {
// delete the first node with a given data
if (head->data == data) {
struct node *temp = head;
head = head->next;
free(temp);
} else {
struct node *n = head;
while (n->next != NULL) {
if (n->next->data == data) {
struct node *temp = n->next;
n->next = temp->next;
free(temp);
break;
}
}
}
return head;
}
void printList(const struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
int main() {
struct node *head = NULL;
head = insertAtBeg(head, 1);
head = insertAtEnd(head, 2);
head = insertAtEnd(head, 3);
printList(head);
head = insertAtBeg(head, 0);
printf("after insertion at beginning\n");
printList(head);
head = insertAtEnd(head, 4);
printf("after insertion at End\n");
printList(head);
head = deleteElement(head, 0);
printf("after deletion at head in main\n");
printList(head);
// should free the list
return 0;
}
An alternative is to pass the address of the list head pointer so the function can modify it if needed.
Here is a modified version of your code with this alternative approach:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insertAtBeg(struct node **headp, int data) {
struct node *temp = malloc(sizeof(*temp));
if (temp != NULL) {
temp->data = data;
temp->next = *headp;
*headp = temp;
}
return temp;
}
struct node *insertAtEnd(struct node **headp, int data) {
struct node *temp = malloc(sizeof(*temp));
if (temp != NULL) {
temp->data = data;
temp->next = NULL;
if (*headp == NULL) {
*headp = temp;
} else {
struct node *n = *headp;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
}
}
return temp;
}
int deleteElement(struct node **headp, int data) {
// delete the first node with a given data
struct node *head = *headp;
if (head->data == data) {
*headp = head->next;
free(temp);
return 1; // node was found and freed
} else {
struct node *n = head;
while (n->next != NULL) {
if (n->next->data == data) {
struct node *temp = n->next;
n->next = temp->next;
free(temp);
return 1; // node was found and freed
}
}
return 0; // node not found
}
}
void printList(const struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
int main() {
struct node *head = NULL;
insertAtBeg(&head, 1);
insertAtEnd(&head, 2);
insertAtEnd(&head, 3);
printList(head);
insertAtBeg(&head, 0);
printf("after insertion at beginning\n");
printList(head);
insertAtEnd(&head, 4);
printf("after insertion at End\n");
printList(head);
deleteElement(&head, 0);
printf("after deletion at head in main\n");
printList(head);
// free the list
while (head != NULL) {
deleteElement(&head, head->data);
}
return 0;
}
This alternative approach uses double pointers, so it is a bit more difficult for beginners to comprehend, but it has a strong advantage: the functions can update the list pointer and provide a meaningful return value that can be tested to detect errors. For example insertAtBeg() and insertAtEnd() return NULL if the new node could not be allocated but preserve the list. Similarly deleteElement() can return an indicator showing whether the element was found or not.
With this approach, you can write functions to pop the first or last element of the list, or the one at a given index, or one with a given data, while updating the list pointer as needed.
In the function void deleteElement(struct node *head,int data) you are passing a pointer to the head node. If you make changes to the node, then that works because you are pointing to the actual node. However, the variable head is a local copy of the pointer, which is not the one in main. When you change head to head->next that is only changing the local copy, so it has no effect outside deleteElement.
ADVANCED LEVEL POINTERS
To actually change head you have to pass a pointer to it, making a double pointer:
void deleteElement(struct node **phead,int data) {
struct node *temp;
temp = *phead;
*phead = (*phead)->next;
this means you have to pass the address of head &head as the parameter.

Linked List elements not getting displayed

This is my program in C which always inserts into a linked list at the end. But when I try to print the list elements, nothing is displayed. Here is the code :
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void insert(struct Node *, int);
int main(void)
{
struct Node *head = NULL, *current;
int n, i, x, data;
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &data);
insert(head, data);
}
current = head;
while(current != NULL)
{
printf("%d ", current->data);
current = current->next;
}
}
void insert(struct Node *head, int data)
{
struct Node *newnode, *current = head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(head == NULL)
{
head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
I cannot understand what might be the issue. Please help.
Your insert cannot modify head. Change it to
void insert(struct Node **head, int data)
and change it by
*head = newnode;
and call it like this
insert(&head, data);
Here, while you are passing the head pointer to your insert() function, it is not being updated in your main() function.
So, either declare your head pointer as global or return your head pointer and update it in your main() function.
In the below code I had taken the head pointer as global and removed the head pointer as your parameter from the insert() function.
Here is the code :-
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node *head=NULL;
void insert(int);
int main(void)
{
struct Node *current;
int n, i, x, data;
clrscr();
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &data);
insert(data);
}
current = head;
while(current != NULL)
{
printf("%d \n", current->data);
current = current->next;
}
getch();
return 0;
}
void insert(int data)
{
struct Node *newnode, *current = head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(head == NULL)
{
head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
You need to pass the reference of the head pointer, then only the changes made to it will be visible.
You must declare your function like
void insert(struct Node **, int);
and also call it like
insert(&head, data);
also, make changes to function definition
void insert(struct Node **head, int data)
{
struct Node *newnode, *current = *head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(*head == NULL)
{
*head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
You need to pass the head by reference as you are making changes to it that should be visible.
insert(head, data);
should become
insert(&head, data);
Also the function signature will change.
void insert(struct Node *head, int data)
should become
void insert(struct Node **head, int data)
Also make appropriate changes in the function.
Like,
current = *head;
Because you are passing the pointer by value. The function operates on a copy of the pointer, and never modifies the original.
Either pass a pointer to the pointer (i.e. a struct head **), or instead have the function return the pointer.
You can try running the following code which will give the output as null
printf("%s",head);
while(current != NULL)
{
printf("%d", current->data);
current = current->next;
}

Linked list implementation in C(printing only last two nodes)

#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node *next;
};
void addLast(struct node **head, int value);
void printAll(struct node *head);
struct node *head1 = NULL;
int main() {
addLast(&head1, 10);
addLast(&head1, 20);
addLast(&head1, 30);
addLast(&head1, 40);
printAll(head1);
return 0;
}
void addLast(struct node **head, int value) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
(*head)->next = NULL;
} else {
struct node **temp = head;
while ((*temp)->next != NULL) {
*temp = (*temp)->next;
}
(*temp)->next = newNode;
newNode->next = NULL;
}
}
void printAll(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d->", temp->data);
temp = temp->next;
}
printf("\n");
}
addLast() will append the new node at the end of the list, with printAll(), I am printing entire list.
Every time when I am printing the list, I can only see the last two nodes.
Can anyone please help, why loop is not iterating over entire list ?
The function addLast is too complicated and as result is wrong due to this statement
*temp = (*temp)->next;
in the while loop. It always changes the head node.
Define the function the following way
int addLast( struct node **head, int value )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = value;
newNode->next = NULL:
while( *head ) head = &( *head )->next;
*head = newNode;
}
return success;
}
Take into account that there is no need to declare the variable head1 as global. It is better to declare it inside the function main.
Also all the allocated memory should be freed before exiting the program.

incompatible pointer type in c pointers

#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
int insert (struct node *head, int data);
int print (struct node *head);
int main()
{
struct node *head;
head = NULL;
// printf("%d\n",head);
insert(&head,5);
insert(&head,4);
insert(&head,6);
print(&head);
print(&head);
print(&head);
}
int insert(struct node *head,int data) {
if(head == NULL) {
head = malloc(sizeof(struct node));
head->next = NULL;
head->data = data;
// printf("%d\n",data);
}
else {
struct node *tmp = head;
if(tmp->next!=NULL) {
tmp = tmp->next;
}
tmp->next = malloc(sizeof(struct node));
tmp->next->next = NULL;
tmp->next->data = data;
// printf("%d\n",data);
}
}
int print (struct node *head) {
printf("hello entered here\n");
struct node *tmp = head;
if (head == NULL) {
printf("entered null\n");
return;
}
while (tmp != NULL) {
if (tmp->next == NULL) {
printf("%0d", tmp->data);
} else {
printf("%0d -> ", tmp->data);
}
tmp = tmp->next;
}
printf("\n");
}
I got the following warning when i compile it
In function main:
insert.c:16: warning: passing argument 1 of insert from incompatible pointer type
insert.c:17: warning: passing argument 1 of insert from incompatible pointer type
insert.c:18: warning: passing argument 1 of insert from incompatible pointer type
insert.c:19: warning: passing argument 1 of print from incompatible pointer type
insert.c:20: warning: passing argument 1 of print from incompatible pointer type
insert.c:21: warning: passing argument 1 of print from incompatible pointer type
When i run it i will get following output
hello entered here
0 -> 5 -> 6
hello entered here
0 -> 5 -> 6
hello entered here
0 -> 5 -> 6
Please help me remove this warnings.
And can u also help me add a function to remove the node in C
What is the mistake I am doing?
Should i pass **head to the function?
Currently the functions print() and insert() expects to struct node* whereas you pass struct node **. If you want to pass a copy then drop the & in your function calls in your code.
If you want to modify the pointer head pass a pointer to pointer and modify the parameters accordingly:
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
int insert (struct node **head, int data);
int print (struct node **head);
int main()
{
struct node *head;
head = NULL;
// printf("%d\n",head);
insert(&head,5);
insert(&head,4);
insert(&head,6);
print(&head);
print(&head);
print(&head);
}
int insert(struct node **head,int data){
if(*head == NULL){
*head = malloc(sizeof(struct node));
(*head)->next = NULL;
(*head)->data = data;
// printf("%d\n",data);
}
else {
struct node *tmp = *head;
if(tmp->next!=NULL){
tmp = tmp->next;
}
tmp->next = malloc(sizeof(struct node));
tmp->next->next = NULL;
tmp->next->data = data;
// printf("%d\n",data);
}
}
int print (struct node **head) {
printf("hello entered here\n");
struct node *tmp = *head;
if (*head == NULL) {
printf("entered null\n");
return;
}
while (tmp != NULL) {
if (tmp->next == NULL) {
printf("%0d", tmp->data);
} else {
printf("%0d -> ", tmp->data);
}
tmp = tmp->next;
}
printf("\n");
}
Your insert() smells - too complicated. This is some sort of OO actually.
Here is my way, direct typed:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// class node_t
typedef struct __node_s *node_t; // Mind the pointer here.
struct __node_s {
int data;
node_t next;
};
node_t node_init(void); // Constructor.
void node_append(node_t, int);
void node_drop_last(node_t);
void node_print(node_t);
void node_fini(node_t); // Destructor.
// end class node_t
int main(void)
{
node_t head = node_init();
node_append(head, 5);
node_append(head, 4);
node_append(head, 6);
node_print(head);
node_drop_last(head);
node_print(head);
node_fini(head);
head = NULL;
return 0;
}
node_t node_init(void)
{
node_t node = malloc(sizeof(struct __node_s));
assert(node);
memset(node, 0, sizeof(struct __node_s));
return node;
}
void node_insert(node_t head, int data)
{
node_t last = head, new = node_init();
for (; last->next; last = last->next);
new->data = data;
last->next = new;
}
void node_drop_last(node_t head)
{
node_t last = head;
if (!head->next)
return;
for (; last->next->next; last - last->next);
node_fini(last->next);
last->next = NULL;
}
void node_print(node_t head)
{
for (node_t this = head->next; this; this = this->next)
{
printf("%d", this->data);
if (this->next)
putchar(' '); // A lot faster!
}
putchar('\n');
}
void node_fini(node_t head)
{
if (head->next)
{
node_fini(head->next);
head->next = NULL;
}
free(head);
}

Resources