Traverse linked list with recursive method - c

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.

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.

how to delete head in a linked list in 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;
}

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?

Printing a linked list of integers in C

I'm trying to get an integer of any size to a linked list in C. But when I print the list, a zero is printed always after the the integer.
Please note that I'm adding each digit of the integer to the head.(head has the 0th place of the integer)
#include <stdio.h>
#include <stdlib.h>
struct node
{
int digit;
struct node* next;
};
void get_number(struct node** head);
int create_node(int digit, struct node** head);
void printlist(struct node* head);
int main()
{
struct node* head1 = malloc(sizeof(struct node*));
get_number(&head1);
printlist(head1);
return 0;
}
int create_node(int digit, struct node** head)
{
struct node* tmp = malloc(sizeof(struct node*));
tmp -> digit = digit;
tmp -> next = *head;
*head = tmp;
}
void printlist(struct node* head)
{
struct node* curr = head;
if(!head)
return;
while(curr != NULL )
{
printf("%d",curr -> digit);
curr = curr -> next;
}
}
void get_number(struct node** head)
{
int k;
char c;
c = getchar();
while(c != '\n' && c != ' ')
{
k = c - '0';
create_node(k, head);
c = getchar();
}
}
when I input 123456, the output is 1234560.
I tried to find solution, but couldn't. Please help
You are one more node than necessary when you allocate to head1. You simply need to call the function get_number() as:
struct node* head1 = 0;
get_number(&head1);
which would set the next of the last element (i.e. the first allocate node) to 0 and rest of the logic would be fine.
You also need to correctly call malloc() and change the type of c to int (to handle EOF) as noted in the comments. My preferred way is to allocate memory is:
TYPE *p = malloc(sizeof *p);

What is wrong with my code for singly linked list?

I'm working on a singly linked list in C. This is what I've written so far.
C program
#include<stdio.h>
#include<stdlib.h>
struct Node{
int value;
struct Node *next;
};
struct Node* init()
{
struct Node* head=NULL;
head=malloc(sizeof(struct Node));
head->value=-1;
return head;
}
int length(struct Node* head)
{
struct Node* current=head;
int length=0;
while(current!=NULL)
{
length++;
current=current->next;
}
return length;
}
void print(struct Node* head)
{
int i=0;
int len=length(head);
for(i=0;i<len;i++)
{
printf("%d%d",i,head[i].value);
printf("\n");
}
}
struct Node* insert(int data,struct Node* head)
{
struct Node* current=NULL;
if(length(head) > 0)
{
int val=head->value;
if (val==-1)
{
head->value=data;
head->next=NULL;
}
else
{
current=malloc(sizeof(struct Node));
current->value=data;
current->next=head;
head=current;
}
}
else
{
printf("List is empty");
}
return head;
}
int main()
{
/* printf("Hello"); */
struct Node *head=init();
head=insert(20,head);
head=insert(30,head);
head=insert(40,head);
print(head);
printf("%d",length(head));
return 0;
}
The output values I get are:
Index Value
0 40
1 0
2 0
and for length is 3. I'm not able to grasp what I'm doing wrong here in pointer manipulation.
One obvious problem is not setting next to NULL on init - that would fail when checking length on the empty list
But your real problem is the print function
You can't use:
head[i].value
That notation is only valid for arrays, you need to use next to find each member
The Init function should set Next to NULL
struct Node* init()
{
struct Node* head=NULL;
head=malloc(sizeof(struct Node));
head->value=-1;
head->next=NULL;
return head;
}
otherwise the first call to length return an undefined result ( or GPF ).
Here:
for (i = 0; i < len; i++)
{
printf("%d%d", i, head[i].value);
printf("\n");
}
You need to advance from one node to another with head = head->next in the same manner as you do it in length(). head[i] won't do it.
It's unclear why your init() and insert() are so unnecessarily complicated and I don't even want to try to guess why. I want to suggest a better insert() and no init():
struct Node* insert(int data, struct Node* head)
{
struct Node* current;
current = malloc(sizeof(struct Node));
current->value = data;
current->next = head;
return current;
}
And then you do this:
int main(void)
{
struct Node *head = NULL;
head = insert(20, head);
head = insert(30, head);
head = insert(40, head);
print(head);
printf("%d", length(head));
return 0;
}
The notation head[i].value is only valid for arrays but not for linked lists. Arrays and linked lists are completely different, allocation of memory towards arrays is premeditated where as for linked lists it's dynamic. That is the reason why we use pointers for linked lists.
In init() you didn't assign null which causes the loop to run infinite times when you call length() for first time.
I am posting the modified code of print function:
void print(struct Node* head)
{
int i=0;
int len=0;
struct Node* current=head;
for(i=0;i<len;i++)
{
printf("%d %d",i,current->value);
print("\n");
current=current->next;
}
}

Resources