how to delete head in a linked list in c? - c

This program should delete the N-node in a singly linked list. If i put N = 1 or N = 2 it's ok, the program works. But with N = 0 the output prints infinite nodes with random values (after deleting the node 0). I think the program can't see the new head. Thx for the help!
#include <stdio.h>
#include <stdlib.h>
#define N 0
struct node {
int data;
struct node *next;
};
void printlist(struct node *head){
struct node *current=head;
int i=0;
while (current!=NULL){
printf("node number %d \t : %d\n", i, current->data);
current=current->next;
i++;
}
}
int deletenode(struct node *head,int n){
struct node *current=head;
struct node *previous=head;
int i=0;
while(current!= NULL){
if (n==i && i!=0){
previous->next=current->next;
free(current);
return 1;
}
else if (n==i && i==0){
head=head->next;
free(current);
return 1;
}
i++;
previous=current;
current=current->next;
return 0;
}
printf("error\n");
exit(EXIT_FAILURE);
}
void main(){
struct node *n1=malloc(sizeof(struct node));
struct node *n2=malloc(sizeof(struct node));
struct node *n3=malloc(sizeof(struct node));
struct node *head=n1;
n1->data=5;
n1->next=n2;
n2->data=10;
n2->next=n3;
n3->data=15;
n3->next=NULL;
printf("\n\nbefore\n");
printlist(head);
deletenode(head,N);
printf("\n\nafter\n");
printlist(head);
}
I'm using currentas a temp pointer , because after the head shift on the second node i need a pointer to the old head and use free.

C always passes by value, so changing a parameter has no effect on the caller.
void foo(int i) {
i = 1234; // No effect on caller.
}
void foo(int *p) {
p = NULL; // No effect on caller.
}
If you want to modify a variable (such as the caller's head), you need to pass a pointer to it. (You can still change that to which a pointer references.)
int deletenode(struct node **head, int n) {
...
}
deletenode(&head, N);
Now, you could simply replace every instance of head in your code with (*head) to account for the new calling convention, but that would waste an opportunity for simplification. By having a pointer to a struct node *, we don't need to handle head (a struct node *) and prev_node->next (a struct node *) differently.
int delete_node_n(struct node **ptr, unsigned n) {
// Make `ptr` point to the pointer we want to modify.
// This will either be the `head` variable
// or the `next` field of some node.
while (1) {
if (!*ptr)
return 0;
if (!n)
break;
ptr = &( (*ptr)->next );
--n;
}
struct node *to_free = *ptr;
*ptr = (*ptr)->next;
free(to_free);
return 1;
}

Related

debug an array of linked lists in c

I'm having a trouble in my project, at first I made one linked list and it worked properly but then I had to edit it and make it an array of linked list, but it just stores in a wrong way I guess, here is my code, what's wrong with it?
#include <stdio.h>
#include <stdlib.h>
struct node
{
int coeff;
int power;
struct node* Next;
};
void Insert(int X,int Y, struct node* L, struct node* P)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->coeff = X;
temp->power = Y;
temp->Next = P->Next;
P->Next = temp;
}
void PrintList(struct node* L)
{
struct node* P = L;
printf("%d %d ",P->coeff,P->power);
printf("\n");
P=P->Next;
}
int main()
{
struct node* head[3] ;
for(int q =0 ; q!= 3 ; q++)
{
head[q] = malloc(sizeof(struct node));
}
Insert(1,2,head[0],&head[0]);
Insert(2,3,head[0],&head[0]);
Insert(1,2,head[1],&head[1]);
Insert(2,2,head[1],&head[1]);
for(int i=0 ;i!=3;i++){
PrintList(head[i]);
}
return 0;
}
In a LinkedList there is only 1 head. You have allocated 3 different heads and are trying to add nodes to these heads. So the following answer assumes you intend to have 3 different LinkedLists with each list's head in an array.
The memory from malloc() in this line
head[q] = malloc(sizeof(struct node));
was uninitialized. Using calloc() appeared more prudent here. So,
head[q] = calloc(sizeof(struct node), 1); //Initialize everything to 0
Next, one of the arguments in your Insert() was redundant and also didn't go with your calling code. It is of the signature
void Insert(int ,int , struct node* , struct node*)
but you're invoking it with
void Insert(int ,int , struct node* , struct node**)
Dropping the last argument should be fine, I guess, in this case since you aren't modifying the incoming struct node* pointer but its contents instead. In case you were changing the struct node* to point to something else within the Insert() function (e.g. P = temp; etc.), then passing in a struct node** would have more meaning. So, changing your code to
void Insert(int X,int Y, struct node* P)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->coeff = X;
temp->power = Y;
temp->Next = P->Next;
P->Next = temp;
}
And the calling code to
Insert(2,3,head[0]);
Insert(1,2,head[0]);
Insert(1,2,head[1]);
Insert(2,2,head[1]);
Next, changing your PrintList to actually traverse the LinkedList:
void PrintList(struct node* L)
{
struct node* P = L;
while(P) {
printf("%d %d\n",P->coeff,P->power);
P=P->Next;
}
}
Apart from that, I just added some logging to better clarify the LinkedList being printed.
for(int i=0 ;i!=3;i++){
printf("Printing list %d:\n", i);
PrintList(head[i]);
printf("*****\n");
}
This gives the output:
Printing list 0:
0 0
1 2
2 3
*****
Printing list 1:
0 0
2 2
1 2
*****
Printing list 2:
0 0
*****
Obviously, all the head of the LinkedLists are 0 initialized and hence show up as 0 0. They could be initialized as deemed fit, or could be dropped from the PrintList() function altogether, depending on your program's expectations.
When working on a C project you should always enable compiler warnings. If you do the compiler will issue a warning like
warning: passing argument 4 of ‘Insert’ from incompatible pointer type [-Wincompatible-pointer-types]
This is just the first problem in your code. You also have uninitialized fields in the nodes you allocate in the main function.
Instead of having a function which modifies the list, it is more flexible to define a function which adds a new node to a list and returns the new list. Below is an alternative approach which also uses convenience macro functions for allocating memory and calculating the length of an array. The code also hides the pointer behind a type definition and defines a function which frees a list.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(array) ((int) (sizeof (array) / sizeof (array)[0]))
#define NEW_ARRAY(pointer, length) \
{ \
(pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); \
if ((pointer) == NULL) { \
fprintf(stderr, "Allocating memory with malloc failed: %s\n", strerror(errno)); \
exit(EXIT_FAILURE); \
} \
}
#define NEW(pointer) NEW_ARRAY((pointer), 1)
typedef struct node *List;
struct node {
int coeff;
int power;
struct node *next;
};
List NewList(int coeff, int power, List next)
{
List node;
NEW(node);
node->coeff = coeff;
node->power = power;
node->next = next;
return node;
}
void FreeList(List list)
{
if (list != NULL) {
FreeList(list->next);
free(list);
}
}
void PrintList(List list)
{
while (list != NULL) {
printf("%d %d\n", list->coeff, list->power);
list = list->next;
}
}
int main(void)
{
List head[3] ;
head[0] = NewList(1, 2, NewList(2, 3, NULL));
head[1] = NewList(1, 2, NewList(2, 2, NULL));
head[2] = NULL;
for (int i = 0; i < LEN(head); i++) {
PrintList(head[i]);
FreeList(head[i]);
}
return 0;
}

Traverse linked list with recursive method

I need to go through a list linked by the middle of a function with a parameter that is a triple pointer, by means of a recursive void function.
The program is as follows
typedef struct node
{
int data;
struct node* next;
}Node;
void insert(Node** first,int d){
Node* new= createNode(d);
new->next= *first;
*first=new;
}
Node* createNode(int d){
Node* new= (Node*)malloc(sizeof(Node));
new->data= d;
new->next=NULL;
return new;
}
void printList(Node***p)
{
Node**temp = *p;
if(temp == NULL)
return;
else
{
printf("\nValue: %d", (*temp)->data);
*temp = (*temp)->next;
printList(&temp);
}
}
int main()
{
Node *first = NULL;
int n =10;
while(n>0){
insert(&first,n);
n=n-1;
}
Nodo **ptr_first= &first;
printList(&ptr_first);
return 0;
}
The function prints all the values, but the program hangs and returns a negative value. What is wrong with this implementation?
PD: The use of the triple pointer is only for teaching purposes
Your recursion termination condition is wrong.
You have tho change if(temp == NULL) to if(*temp == NULL), since *temp is pointing to the element and not temp.
I also think that it is not good for teaching if you use triple pointers since they are not necessary here.

different ways of adding node in linked list

This simple code (adding element to linked list and printing it) works fine
#include <stdio.h>
struct node{
int item;
struct node* next;
};
void print_node (struct node* n){
while (n!= NULL){
printf("%d ", (*n).item);
n = n->next;
}
printf("\n");
}
void append_node(struct node *list, struct node *n){
while(list->next != NULL)
list = list->next;
list->next = n;
}
int main(){
struct node n1, n2;
n1.item = 1;
n1.next = NULL;
n2.item = 2;
n2.next = NULL;
print_node(&n1);
print_node(&n2);
append_node(&n1,&n2);
print_node(&n1);
printf("done\n");
return 0;
}
If instead I define the append_node as following
void append_node(struct node *list, struct node n){
while(list->next != NULL)
list = list->next;
list->next = &n;
}
and call it accordingly in the main (i.e., append_node(&n1, n2) ) I get a segmentation fault when running the program. And I don't understand why :)
When you call append_node(struct node *list, struct node n), the argument n is copied on the function context.
When the function is leave, the context is freed, and the copy n of your data is lost.
You could use your function append_node(struct node *list, struct node n) if you make a copy of n (using malloc) before putting it in linked list.
EDIT
This may help you: What's the difference between passing by reference vs. passing by value?

Linked List inserting trouble

I am having trouble with inserting items in linked list. All the elements end up having the same *data content that is inserted in the last. The program compiles successfully. I use gcc and gdb.
I am new to coding so please mention troubles if any that you see in my programming style.
typedef struct Node{
void* data;
struct Node* next;
} *node;
node allocate(){
node current = malloc(sizeof(struct Node));
current->data = NULL;
current->next = NULL;
return current;
}
void insert(node *head, void *data){
// if head has no data then set the data on head and return
if(((*head)->data == NULL)&&((*head)->next == NULL)){
(*head)->data = data;
return;
}
node newHead = allocate();
newHead->data = data;
newHead->next = *head;
*head = newHead;
//printf("Node Data : %d\tNext Node Data : %d",
//*(int *)((*head)->data), *(int *)((*head)->data));
}
int main(int argc, char *argv[]){
node head = allocate();
int count = inputSequence(&head);
int *aod = calloc((size_t) count, sizeof(int));
generateAOD(head, aod);
if(checkJolly(aod, count) == TRUE)
printf("Jolly\n");
else
printf("Not Jolly\n");
return 0;
}
int inputSequence(node *input){
int *num = malloc(sizeof(int));
int count = 0;
while((scanf("%d", num) != EOF)){
insert(input, (void *)num);
count++;
}
traverse(*input, fn);
return count;
}
Your insert logic is non-existant. And you're literally making your life harder by attempting to manage a linked list in the fashion you're using.
The head pointer itself should indicate whether the list is empty. If it is NULL, its empty. If it isn't, there's data. Code the insertion logic accordingly.
And your inputSequence is utterly broken. It only allocates ONE data point, then uses the same data allocation for every insertion. You need one for each insertion.
First, change allocate() to accept the data being inserted. It will make the remaining code less cluttered:
node allocate(void *data)
{
node current = malloc(sizeof(*current));
current->data = data;
current->next = NULL;
return current;
}
Second, insert by allocating a new node as needed.
void insert(node *head, void *data)
{
node p = allocate(data);
p->next = *head;
*head = p;
}
Next, fix inputSequence() to properly allocate memory for each entry:
int inputSequence(node *input)
{
int count = 0;
int num = 0;
// note: check for number of params *successfully* parsed.
// if it isn't 1, its time to leave the loop.
while(scanf("%d", &num) == 1)
{
int *data = malloc(sizeof(num));
*data = num;
insert(input, data);
++count;
}
return count;
}
And lastly, make sure your head pointer is initially NULL in main().
int main(int argc, char *argv[])
{
node head = NULL;
// load linked list
inputSequence(&head);
// ... the rest of your code....;
return 0;
}
With the above, the logical answer of "Is my list empty" is simply if (!head) Further, this makes things like traversal trivial.
void traverse(node ptr, void (*pfn)(void *))
{
while (ptr)
{
pfn(ptr->data);
ptr = ptr->next;
}
}
Freeing the list is equally trivial:
void destroy(node *head)
{
while (*head)
{
node p = *head;
*head = p->next;
free(p->data);
free(p);
}
}
typedef struct Node{
void* data; // Make it as int or any other data type
struct Node* next;
} *node;
In function inputSequence() you are allocating memory for num at the very beginning and making node->data point to this memory each time you are adding a node. Hence data pointer of each node of your linked list points to the same memory location and hence contains the same value.
If you still want to continue with data as a void pointer, allocate num for each iteration of the while loop and pass this to insert function.
while((scanf("%d", num) != EOF)){
num = malloc(sizeof(int);
insert(input, (void *)num);
count++;
}

linked list program

I am expecting the below linked list program to print 1
but its not.can anyone figure out why?
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node * link;
};
typedef struct node NODE;
void display(NODE *);
void add(NODE *,int );
int main()
{
NODE *head=NULL;
add(head,1);
display(head);
printf("\n");
getch();
return 0;
}
void display(NODE *pt)
{
while(pt!=NULL)
{
printf("element is");
printf("%d",pt->data);
pt=pt->link;
}
}
void add(NODE *q,int num)
{
NODE *temp;
temp = q;
if(q==NULL)
{
q=(NODE *)malloc(sizeof(struct node));
temp = q;
}
else
{
while((temp=temp->link)!=NULL);
temp->link = (NODE *)malloc(sizeof(struct node));
temp=temp->link;
}
temp->data = num;
temp->link = NULL;
}
Your local variable head in main() is not modified by your add() function. This means you are calling display() with a parameter of NULL.
You'll need to pass a NODE **q into add, then update it in add().
Your add method when called first time (when head == NULL) should add the first node to the list thus changing head to point to the newly allocated node.
But this does not happen as add does not communicate back the changed head to the caller.
To fix this you can either return the modified head from the function:
// call as before but assign the return value to head.
head = add(head,1);
.....
// return type changed from void to NODE *
NODE* add(NODE *q,int num)
{
// make the changes as before
// return the head pointer.
return q;
}
or you can pass the pointer head by address to the function add as:
// pass the address of head.
add(&head,1);
.....
// change type of q from NODE * to NODE **
void add(NODE **q,int num)
{
// same as before but change q to *q.
// any changes made to the list here via q will be visible in caller.
}
The add() function is modifying the q argument, but it is passing it by value. Then head remains NULL after the add() call.
The problem is in signature of add method, to make your program work you should pass pointer to pointer of NODE, like this
void add(NODE **,int );
and work with him.
Then in case
if(*q==NULL)
you can allocate memory and replace NULL pointer to new HEAD
by it
*q=(NODE*)malloc(sizeof(struct node));
So it will work.
The problem is when you allocate memory you just replace local copy of null pointer to NODE but it doesn't affect head in main function.
int main()
{
NODE *head=NULL;
add(head,1);
display(head);
NODE *head is local to main. It's value is NULL. You pass the value NULL to add, which then creates a NODE and sets its data to 1. You then return to main... ...where head is STILL NULL. You need to pass the address of head, so that it's actual value is changed in add(). You also need to change add() to work with a pointer.
Main should return EXIT_SUCCESS or EXIT_FAILURE. Don't typedef struct node; it's harmful to readability and you get no abstraction here from using it.
When you call Add the new head pointer never gets returned. So it still points to NULL.
Ah... you're getting tripped up by the pointers...
Essentially, if you want to modify "head", you need to send a reference to THAT... otherwise you are just modifying the pointer... Change your code to this:
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node * link;
};
typedef struct node NODE;
void display(NODE *);
void add(NODE **,int );
int main()
{
NODE *head=NULL;
add(&head,1);
display(head);
printf("\n");
getch();
return 0;
}
void display(NODE *pt)
{
while(pt!=NULL)
{
printf("element is ");
printf("%d",pt->data);
pt=pt->link;
}
}
void add(NODE **q,int num)
{
NODE *temp;
temp = *q;
if(*q==NULL)
{
*q=(NODE *)malloc(sizeof(struct node));
temp = *q;
}
else
{
while((temp=temp->link)!=NULL);
temp->link = (NODE *)malloc(sizeof(struct node));
temp=temp->link;
}
temp->data = num;
temp->link = NULL;
}

Resources