struct node{
int data; struct node *next;
};
void push(struct node* head, struct node* n){
if(n!= NULL){
if(head==NULL)
head = n;
else {
n->next = head;
head = n;
}
} else printf("Cannot insert a NULL node");
}
struct node* pop(struct node* head){
if(head!=NULL){
struct node *n = head;
head = head->next;
return n;
} else {
printf("The stack is empty");
return NULL;
}
}
int main(){
int i;
struct node *head = NULL, *n;
for(i=15;i>0;i--){
struct node *temp = malloc(sizeof(struct node));
temp -> data = i;
temp->next = NULL;
push(head,temp);
}
n = head;
while(n!=NULL){
printf("%d ",n->data);
n=n->next;
}
return 0;
}
You need to pass the address of the pointer head to the function push. I your case the head is not getting modified because you are only passing the value in the head.
void push(struct node** head, struct node* n){
if(n!= NULL){
if(*head==NULL)
*head = n;
else {
n->next = *head;
*head = n;
}
} else printf("Cannot insert a NULL node");}
int main(){
int i;
struct node *head = NULL, *n;
for(i=15;i>0;i--){
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp -> data = i;
temp->next = NULL;
push(&head,temp);
}
n = head;
while(n!=NULL){
printf("%d ",n->data);
n=n->next;
}
return 0;}
You are passing the head pointer by value to the function push(head,temp);. The changes to head done inside push will not be reflected in the main() function.
You should pass address of head to push().
push(&head, temp);
and inside push():
*head = n;
Similar change will be required for pop(). You can verify what I am saying by adding a printf inside the loop in main() as: printf("%p\n", head);. The value of head will remain unchanged.
BTW, it is good practice to add a \n at the end of statement inside printf, it flushes the stdout stream immmediately hence your output is printed immediately on stdout (your computer screen).
Related
#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.
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;
}
I am trying to create a simple linked list using C, I think I was able to construct the linked list itself, but when I try and print it, it prints the value of the last node instead of all the values in the list.
#include <stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
temp->next = NULL;
printf("%d \n", temp->d);
return 0;
}
Any help/tips would be greatly appreciated.
There are multiple problems in your code:
You are not creating the list properly. You are allocating memory for only one node and playing around with pointers improperly causing the linked list to be pointed to the same memory
You are not calling printList function at all
It is not clear why you are allocating memory again in printList whereas it should be printing the already created list
Also, no need to pass double pointer for printList as you are not modifying the list.
Though you should be understanding and doing the changes yourself, I am providing a below modified program which I hope will help you understand the mistakes in your code.
Please see the below modified version of the code
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
struct Node *createNode()
{
struct Node *newNode;
newNode = malloc(sizeof(struct Node));
if (NULL == newNode)
return NULL;
memset(newNode, 0, sizeof(struct Node));
return newNode;
}
int main()
{
struct Node *newNode = NULL;
struct Node *headNode = NULL;
struct Node *temp = NULL;
int i = 0;
int data = 0;
printf("Enter 3 numbers\n");
for( i = 0; i< 3; i++)
{
scanf("%d", &data);
newNode = createNode();
if (NULL == newNode)
break;
newNode->d = data;
if (headNode == NULL)
{
headNode = newNode;
temp = newNode;
}
else
{
temp->next = newNode;
temp = temp->next;
}
}
printList(headNode);
return 0;
}
Replace your code with the following code :-
#include<stdio.h>
#include <alloca.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
while(temp->next!=NULL)
{
printf("%d \n", temp->d);
temp = temp->next;
}
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for( i = 0; i< 3; i++)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
printList(head);
return 0;
}
Here you need to declare the newNode in the loop also while taking the input. As, the current value is over-writted, the old value is lossed and only the value of last node is printed.
Also while printing, check for temp->next!=Null instead of temp!=NULL
I am having some trouble adding integers to the end of my linked list. I am very new to C and had part of my program working properly (the push function). I want to return a pointer to a struct node, and I am not quite sure where I am going wrong in my append function.
~Thanks.
enter code here
//node.h
#ifndef NODE_H
#define NODE_H
struct node{
int val;
struct node *next;
};
int length(struct node *);
struct node* push(struct node *, int); //adds integer to front of list.
struct node* append(struct node *, int); //adds integer to back of list.
void print(struct node *, int);
#endif
//node.c
#include "./node.h"
#include<stdlib.h>
#include<stdio.h>
int length(struct node *current){
if(current->next != NULL)
return 1 + length(current->next);
else
return 1;
}
struct node* push(struct node *head, int num){
struct node *temp = malloc(sizeof(struct node));
temp->val = num;
temp->next = head;
head = temp;
temp = NULL;
return head;
}
struct node* append(struct node *current, int num){
if(current != NULL){
append(current->next, num);
}
else{
struct node* temp = malloc(sizeof(struct node));
temp->val = num;
temp->next = NULL;
current = temp;
return current;
}
}
void print(struct node* head, int size){
printf("The list is %i", size);
printf(" long \n");
struct node* temp;
temp = head;
while(temp != NULL){
printf("%d", temp->val);
printf(" ");
temp = temp->next;
}
printf(" \n");
}
//Main
#include "./node.h"
#include<stdlib.h>
#include<stdio.h>
int main(){
char ans[2];
int num;
struct node* head = NULL;
do{
printf("Enter a integer for linked list: ");
scanf("%d", &num);
head = append(head, num);
printf("Add another integer to linked list? (y or n) ");
scanf("%1s", ans);
}while(*ans == 'y');
print(head, length(head));
return 0;
}
I think what is missing is that the recursive part of the function needs to set current->next. This has the effect of setting every node's next pointer to what it was until you get to the end of the list, when it is set to the newly malloced node.
struct node* append(struct node *current, int num){
if(current != NULL){
current->next = append(current->next, num);
return current;
}
else {
struct node* temp = malloc(sizeof(struct node));
if (temp == NULL) abort();
temp->val = num;
temp->next = NULL;
return temp;
}
}
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);
}