C: Linked LIst and Pointer to Pointer - c

The struct that will represent the node of the linked list:
typedef struct node{
int val;
struct node *next;
} node_t;
and the head of our list:
node_t *head;
Now, I wanna build a function that creates the first element in the list, of course that will be pointed by *head. I am gonna start with the correct version, in my point of view, of the function, where I used a pointer who points to head, namely a double pointer:
void createFirstElement(node_t **head, int value){
*head=NULL;
*head=malloc(sizeof(node_t));
(*head)->val=value;
(*head)->next=NULL;
}
When I used that version of createFirstElement I got the value of the node printed. However I have a question for my first version of createFirstElement which didn't worked:
void createFirstElement(node_t *head, int value){
head=NULL;
head=malloc(sizeof(node_t));
head->val=value;
head->next=NULL;
}
How is this version different from the one with double pointers? I am still getting the head pointer in parameter (instead of a pointer that points to head) and make all the changes inside.
Thanks everyone in advance!

C uses "call by value", so in the second version you are working with a copy of node_t *head. When the function returns, the head which was passed to the function remains unchanged.

Related

init() function call in C

I am following an online tutorial which presents me with the following (simplified) code:
typedef struct {
int data;
Node* next;
} Node;
int main(){
Node *head;
init(&head);
return 0;
}
What is the purpose & functionality of the init function? I did not define it myself, however am struggling to find documentation online as well.
For starters this declaration
typedef struct {
int data;
Node* next;
} Node;
is incorrect. The name Node used in this data member declaration
Node* next;
is undefined.
You need to write
typedef struct Node {
int data;
struct Node* next;
} Node;
As for your question then in this declaration
Node *head;
the pointer head has an indeterminate value because it is not initialized.
So it seems the function init just initializes the pointer. You need to pass the pointer by reference through a pointer to it. Otherwise the function will deal with a copy of the pointer head. Dereferencing the pointer to pointer you will get a direct access to the original pointer head that can be changed within the function. That is the function can look the following way
void init( Node **head )
{
*head = NULL;
}
Pay attention to that you could just write in main
Node *head = NULL;
without a need to call the function init.
I think that the init function is gonna be implemented in the next videos. I suppose that your teacher wants to use an init function to set some values if you create a new Node (or a struct in this case) to prevent some easter eggs undefined behaviour.

Linked list node memory allocation

In creating a linked list we make a node structure and it consists of both data and a pointer to the next node. Later when we make a function to append elements onto the linked list, we make a temporary node to store the inputted data.
Let’s consider the following program-
#include<stdio.h>
struct node
{
int data;
struct node* link;
}
struct node* root=NULL;
void main(append)
{
struct node* temp;
temp= (struct node*)malloc(sizeof(struct node))
.....
}
My first question set:
In line 11, why do we need to mention (struct node*) before the malloc function?
What is the significance of that?
My second question set:
If we are making a doubly linked list which would have a node structure consisting of 2 pointers (for next and previous node), would we also initialize a pointer (for traversing the list) of the struct node type?
Is there a different way to initialize the pointer in that case?
The significance is to make bugs in your program,
The malloc will return void* and when you assign to your struct somthing* it will convert automaticlly.
You simply don't cast the result of malloc as it returns void* . There is one fine explanation here
A better solution might be :
struct node *temp;
temp = malloc(sizeof *temp);
why do we need to mention '(struct node*)' before the malloc function,
what is the significance of that?
By writing (struct node*) before the malloc function, you are type-casting the return value to the specified type. The cast here is optional and often frowned upon.
if we are making a doubly linked list which would have a node
structure consisting of 2 pointers(...
When making a doubly linked list, you should declare something like:
struct node {
int data;
struct node *next;
struct node *previous;
};
You can allocate space for a node by using the malloc function. The next and previous pointers are again pointers to struct nodes. Call malloc again to allocate space for the next element. For the first node, the previous should be NULL and for the last node, next should be NULL. Here is one implementation.
This is the because the return type of malloc is void*. (struct node*) is a cast using which you tell the compiler that you want to treat the value returned by malloc as a pointer to struct node.
For double linked list you can use,
struct node
{
int data;
struct node *next,*prev;
};
int main()
{
struct node *new_node=(struct node *)malloc(sizeof(node));
}
malloc returns the void pointer(can be checked and verified at the header ), and so the type casting is necessary while assigning it to the other type of variable.
Request you to read at the link https://www.tutorialspoint.com/cprogramming/c_type_casting.htm

Nodes as a pointer

Why the nodes in a linked list are declared as pointers? Nodes contains the pointer part in it to link to another node. Then why the nodes are itself a pointer?
struct node
{
int data;
struct node *link;
} *start;
Now we introduce nodes as
struct node *tmp;
Now this is a node which is a pointer to data type struct node..but for linking we use the link pointer to link the other node
Why dindnt we coded node as
struct node tmp;
only...is this because of allocating dynamic memory..or something more?
Yes, this is because the nodes are allocated dynamically.
struct node tmp could be using tmp as a dummy or sentinel node, where it's data is not used, only it's next pointer to the actual first node of a list.
struct node *tmp would be using tmp as a pointer to the first node of a list or as a working pointer to some node in a list when scanning a list.
In some cases a list structure is also used:
struct list{
struct node *head // pointer to first node
struct node *tail // optional: pointer to last node
size_t size; // optional: number of items in a list
}
A circular list could be implemented using just a tail pointer to the last node, which in turn would have a next pointer to the head/first node.

Is it a Linked list implementation?

I am just learning pointers in C and implemented a singly linked list with 3 elements. Is this the right way of approach. Even if it isn't, does the code which I have written represents a linked list?
#include <stdio.h>
struct node
{
int a;
struct node *link;
};
int main()
{
struct node first;
struct node second;
struct node third;
first.a=1;
first.link=&second;
first.link->a=2;
first.link->link=&third;
first.link->link->a=3;
printf("\n%d",first.a);
printf("\n%d",second.a);
printf("\n%d",third.a);
return 0;
}
The code you have written correctly constructs a singly linked list, but is not a general implementation of a singly linked list data structure. For this, the operations that can be applied to a linked list (for example insert an element at a given position, append an element to the end of the list or count the number of elements in the list) are abstracted out and moved into utility functions.
So, as a next step, try implementing a void append(struct node* head, int value) function that, given a pointer to the head of the list, appends a new node with the given value to the end of the list. Then, try to express the construction of your list using this function.
#include <stdio.h>
struct node
{
int a;
struct node *link;
};
int main()
{
struct node first;
struct node second;
struct node third;
first.a=1;
first.link=&second;
first.link->a = 2;
second.link=&third;
second.link->a=3;
printf("\n%d",first.a);
printf("\n%d",second.a);
printf("\n%d",third.a);
return 0;
}
//the nodes in each struct need to point to the next struct, your code was changing the original destination of first.link from pointing to second and then to third,
it cannot point to both, second contains pointer to third, third would contain pointer to fourth....

create Linked List in C

Hello I am so confused about this, I hope you can help me. Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node{
int x;
struct node *next;
struct node *prev;
};
typedef struct node NODE;
NODE * create(int data)
{
NODE *newn;
newn=(NODE*)malloc(sizeof(NODE));
newn->x=data;
newn->next=NULL;
newn->prev=NULL;
return newn;
}
int insert(NODE *list, int data)
{
NODE *temp,*news;
temp=list;
if(list==NULL)
{
list=create(data);
return 0;
}
}
int main()
{
int put;
NODE *mList=NULL;
clrscr();
printf("data: ");
scanf("%i",&put);
insert(mList,put);
}
It is a very simple doubly linked list but I cannot even start inserting because I cannot even put value into the first node. When I create the new node in create, the newn->x will have the right value, and list->x (in insert) will also have the right value but when it goes back to main, mList->x is still 0.
You're passing the mList pointer by value, therefore it resets when the function returns.
Switch to
insert(NODE** list, int data)
and pass it by
insert(&mList, put);
Then I think it'll work. Everytime you want a function to change something you need to pass the argument by pointer, or possibly by reference if you ever move to C++.
I am actually surprised that mList is non-zero after the call to insert.
When you pass mList to insert, a copy of the pointer (mList, which is NULL) is passed to insert. This means that whatever you do with the pointer "list" in the insert function is not reflected in the variable mList (which is outside the function).
You will need to pass address of mList so that you can change what it is pointing to.
So, change the insert method to:
insert(NODE** list, int data)
Change the assignement to list to:
*list = create(data);
and change the call to insert to:
insert(&mList, put);

Resources