Linked List: Insertion at beginning - c

I am a beginner in data structure and I recently wrote a code to insert a new node at the beginning of a linked list using functions but when I run it the inserted node doesn't get printed, please help me verify the error in my code and correct it
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
void
traversal(struct Node *ptr)
{
while (ptr != NULL) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
}
void
insert_first(struct Node *head, int data)
{
struct Node *ptr = (struct Node *) malloc(sizeof(struct Node));
ptr->data = data;
ptr->next = head;
head = ptr;
}
int
main()
{
struct Node *head;
struct Node *second;
struct Node *third;
struct Node *fourth;
head = (struct Node *) malloc(sizeof(struct Node));
second = (struct Node *) malloc(sizeof(struct Node));
third = (struct Node *) malloc(sizeof(struct Node));
fourth = (struct Node *) malloc(sizeof(struct Node));
head->data = 10;
head->next = second;
second->data = 20;
second->next = third;
third->data = 30;
third->next = fourth;
fourth->data = 40;
fourth->next = NULL;
traversal(head);
insert_first(head, 0);
printf("\n");
traversal(head);
return 0;
}

insert_first() function parameter head is a local variable of insert_first() function. So, the statement head = ptr; will make changes in local variable only. These changes will not reflect in the pointer you have passed as first argument to insert_first() function.
As stated in one of the comments that you can return the updated value of head of list and assign that value to original head pointer of list.
Another way could be to pass the address of head pointer of list to insert_first() function (in case, if you want to keep the void as return type of insert_first() function).
For this, you have to changes the type of head parameter of insert_first() function from struct Node * to struct Node ** (double pointer) and pass the address of head (i.e. &head) to insert_first() function. Dereferencing head parameter of insert_first() function will give you the original pointer whose address you have passed and then you can make it point to some other address.
Implementation:
void
insert_first(struct Node **head, int data)
{
struct Node *ptr = (struct Node *) malloc(sizeof(struct Node));
ptr->data = data;
ptr->next = *head;
*head = ptr;
}
and call it like this
insert_first(&head, 0);
^^^
A suggestion:
Follow good programming practise - always check the malloc() return.

Related

Passing a linked list head through a function as address in C

I have a question regarding passing the head of a linked list in C through a function. So the code goes something like this:
#include <stdio.h>
//Defining a structure of the node
struct node {
int data;
struct node* next;
};
void insert (struct node* rec, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
rec = temp; // head and rec is now pointing to the same node
}
void print(struct node* rec){
printf("%d", rec->data); //error occurs here
puts("");
}
main(){
struct node *head = NULL; //head is currently pointing to NULL
insert (head, 5); //Passing the head pointer and integer 5 to insert()
print(head);
}
So as you see, the error occurs when I tried printing rec->data. Why did the error occur? I thought since the pointer rec and head are all pointing to the same node in the heap, there should not be any problem?
Thank you.
You could pass a struct node** as suggested by #sje397.
However, I would suggest the following design (which, in my opinion is easier to reason about too):
/* returns the new head of the list */
struct node *insert (struct node* current_head, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = current_head;
return temp;
}
and use it like
head = insert(head, 5);
In this case I would also rename the function something like push_front.
Just for completeness, I think #sje397 meant something like the following (Typical linked list code rewritten again and again by every C programmer...):
void insert(struct node **head, int x) {
struct node* new_head = (struct node*)malloc(sizeof(struct node));
new_head->data = x;
new_head->next = *head;
*head = new_head;
}
In C there is no pass by reference.
Your insert function isn't inserting a node in the list, its just changing the node which the head points to. Because of temp->next = NULL the list will always contain two nodes.
Another error is that you're just modifying a local copy of the head node.
To fix this You have 3 choices:
-You can make the head node global
-You can pass a pointer to the head node(pointer to pointer) to the function.
-You can return the modified head node by the function.
Redefine the insert function to:
void insert (struct node** rec, int x) {
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
*rec = temp; // head and rec is now pointing to the same node
}

C - Singly linked list - passing a pointer by value vs by reference

typedef struct node { int data; struct node *next; } NODE;
NODE* add_head(NODE **phead, int data) {
NODE *new = (NODE *)malloc(sizeof(NODE));
new->data = data;
new->next = *phead;
*phead = new;
return new;
}
NODE* add_tail(NODE **phead, int data) {
NODE *p, *new = (NODE *)malloc(sizeof(NODE));
new->data = data;
new->next = 0;
if (*phead == 0) *phead = new;
else
{
for (p = *phead; p->next; p = p->next);
p->next = new;
}
return new;
}
We have a singly linked list as shown above in the functions. The node consists of the data type int and the pointer to the next node in the list. We have two functions defined. The first one changes the head node, or adds the new head node before the previous head node. The second function adds the tail node (the last one in the list). In the main, we call them like:
NODE *head = 0;
NODE *c1 = add_head(&head, 1);
NODE *c2 = add_tail(&head, 3);
Now, look at this function:
NODE* add_after(NODE *node, int data) {
NODE *new = (NODE *)malloc(sizeof(NODE));
new->data = data;
new->next = node->next;
node->next = new;
return new;
}
That function adds a node after the argument node. And, in main, if we want to add a node after c1 previously defined, we call the function like:
*c3 = add_after(c1, 4);
My question is: What is the difference between first two and the third function in terms of the arguments. In first two functions, we have an argument **phead and in the third function, *node. Do we really need **phead, why can't we just put *phead and in the main call it like:
NODE *c1 = add_head(head, 1);
I hope you understood what I meant, I find it difficult to explain.
The address of the first element (of type NODE) is contained in a pointer (of type NODE *)
the add_head() functions modifies this pointer. As you are programming in C, blatantly lacking parameter-passing-by-reference, your only option is to transmit its address.
So, the parameter is of type NODE** (adress of a pointer to a NODE).
for add_after() the parameter gives the address of the NODE to be modified. You don't have to modify that address.

C Linked lists with global variables

Hi I'm new to C and I'm struggling to get a linked list working I'm having to use global variables because I can't change the parameters of the function that is being called. I declare the struct and two global pointers to keep track of the root address and last address like this.
struct node {
char* pointer;
struct node *next;
};
struct node** rootNode;
struct node** lastNode;
Then inside the function I malloc a new struct and try to setup the first node in the list. To try and save the location of this node I think I'm assigning the global pointer lastNode to the pointer of root.
struct node *root = malloc(sizeof(struct node));
...
root->pointer=ptr;
root->next = 0;
rootNode = &root;
lastNode = &root;
Then I try to add aditional nodes by mallocing another node and then linking the previous node using the address stored in my lastNode pointer.
struct node *newNode = malloc(sizeof(struct node));
newNode->pointer=ptr ;
(*lastNode)->next = newNode;
newNode->next = 0;
lastNode = &newNode;
However this doesn't really seem to work. When I run the following the program matches the first two items in the list but then returns null for all nodes after that. I've been stuck on this for 2 days now and any help would really be appreciated :)
struct node* test;
test = (*rootNode);
enter code here
while (test) {
if (test->pointer == ptr) {
printf("MATCH!!");
notFound = 0;
break;
}
else {
test = test->next;
}
}
EDIT A couple of people have asked me to supply some more code. This is the function in which I would like to create the linked list. It's called multiple times while my program is running and I'm trying to add a new node to my linked list every time it gets called. I've also included the global variables at the top.
struct node** rootNode;
struct node** lastNode;
int firstRun = 1;
struct node {
char* pointer;
struct node *next;
};
void malloc(size_t sz) {
size_t maxSize = (size_t)-1;
char * payloadPtr = NULL;
if (sz > maxSize - sizeof(struct node)+sizeof(int)) {
return ptr;
}
if (firstRun) {
struct node *root = malloc(sizeof(struct node));
ptr = malloc(sizeof(size_t)+sz);
if (ptr == NULL) {
return ptr;
}
memcpy(ptr, &sz, sizeof(int));
payloadPtr = ptr+1;
root->pointer=payloadPtr;
root->next = 0;
rootNode = &root;
lastNode = &root;
firstRun = 0;
}
else {
struct node *newNode = malloc(sizeof(struct node));
ptr = malloc(sizeof(size_t)+sz);
if (ptr == NULL) {
return ptr;
}
memcpy(ptr, &sz, sizeof(int));
payloadPtr =ptr+1;
newNode->pointer= payloadPtr;
(*lastNode)->next = newNode;
newNode->next = 0;
lastNode = &newNode;
}
return payloadPtr;
}
There's a little clarification about changing the parameters into a function. In C you can only pass by pointers on function calls so if you want to modify the value of a struct node - you pass it like struct node * in the function. Similarly if you want to change the value of a struct node * in the function (as in allocate it or delete it) you may want to pass it like struct node **.
Your function prototype will probably have to look like this:
void addNode(struct node** root, char* value)
But you can also make that root node a local and also just a struct node * instead of struct node **. And then simply call it like:
addNode(&root, value);

Syntax for pointer to pointer when passing to parameters (in C) [duplicate]

This question already has answers here:
pointer to a pointer in a linked list
(2 answers)
Closed 9 years ago.
Yesterday I was trying to implement a linked list and although it worked and I "sort of" understand, it fried my brain a little bit.
What is wrong with function addNode() here?
#include <stdio.h>
struct Node
{
int value;
struct Node *next;
};
struct Node *createList();
void addNode(struct Node* head, int value); // Adds Node directly after head
void viewList(struct Node *head); // Outputs list starting from head
int main()
{
struct Node *head = createList();
addNode(head, 10);
addNode(head, 8);
addNode(head, 23);
addNode(head, 5);
addNode(head, 4);
addNode(head, 4100);
viewList(head); // I didn't upload here to save space
return 0;
}
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
void addNode(struct Node* head, int value)
{
if(head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = head;
head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = head;
head = newNode;
}
}
The reason I am confused is because that version of add node did not work whilst this one did...
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
and that was called in the main function using an amperand in front of the head node pointer
addNode(&head, 10);
The thing that also baffles me is this. I have written some practise functions that accepts a pointer in the parameter list and within the function, modifies what the pointer is pointing to. I never had to use this **pointer syntax.
It has to do with that parameters are passed by value. So in the first, non-working version, the pointer to head is passed by value so the variable is a local variable inside the function. Changes to local variables are not visible outside the function when the function returns.
However, in the second version you pass the pointer by reference, so the function knows where in memory the actual pointer is and can store directly in that memory.
ASCII-diagram time:
Lets say you have the following three variables:
int value1;
int *pointer1 = &value1;
int **pointer2 = &pointer1;
The memory for the variables look something like this:
+----------+ +----------+ +--------+
| pointer2 | --> | pointer1 | --> | value1 |
+----------+ +----------+ +--------+
So pointer2 points to pointer1, and pointer1 points to value1.
Using the dereference operator * on pointer2 will get the value of what pointer2 points to, i.e. pointer1.
Stylistic (don't repeat yourself) ::
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
You don't need the if/else ::
#include <stdlib.h>
void addNode(struct Node **head, int value)
{
struct Node *newNode = malloc(sizeof *newNode);
if ( !newNode) { error(); return;}
newNode->value = value;
newNode->next = *head; // Could be NULL, but we need a NULL anyway in that case
*head = newNode;
}
This here will not work well
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
after you allocate a node and have head pointing to it you set head to point to NULL.
Here it is:
You have a bug with createList
struct Node *createList()
{
struct Node *head = malloc(sizeof(*head));
head->value = 0; //< Probably you want this
head->next = NULL; //< You definitively wanted this
return head;
}
If you are adding nodes to the tail of the list, then addNode would look like:
void addNodeLast(struct Node* head, int value)
{
struct Node *tailNode;
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = NULL;
// Find the last node in the list
for (tailNode = head; tailNode->next; tailNode = tailNode->next);
tailNode->next = head->next;
}
If you are inserting nodes after the head:
void addNodeAfterHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head-next;
head->next = newNode;
}
If you are changing the head (making new head every time):
Node *addNodeNewHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head;
return newNode;
}
...
Node * head = createList();
head = addNodNewHead(head, 3);
head = addNodNewHead(head, 5);

dealing with array of linked list

My approach:
An array of fixed-length (lets say 20) each element is pointer to the first node of a linked list.
so i have 20 different linked list.
This is the structure:
struct node{
char data[16];
struct node *next;
};
My declaration for that array
struct node *nodesArr[20];
now to add a new node to one of the linked list, i do this:
struct node *temp;
temp = nodesArr[i]; // i is declared and its less than 20
addNode(temp,word); // word is declared (char *word) and has a value ("hello")
The addNode function:
void addNode(struct node *q, char *d){
if(q == NULL)
q = malloc(sizeof(struct node));
else{
while(q->next != NULL)
q = q->next;
q->next = malloc(sizeof(struct node));
q = q->next;
}
q->data = d; // this must done using strncpy
q->next = NULL;
}
and to print data from the array of linked list, i do this:
void print(){
int i;
struct node *temp;
for(i=0 ; i < 20; i++){
temp = nodesArr[i];
while(temp != NULL){
printf("%s\n",temp->data);
temp = temp->next;
}
}
}
now compiler gives no error, the program run and i pass the data to it, and when i call print it doesn't print any thing,,??
UPDATE::
after I edited the code (thx for you), i think the problem in the print function,, any idea ?
The problem lies in addNode(). When the list is empty you do:
q = malloc(sizeof(struct node));
but the scope of q is limited to addNode(). You should have declared addNode() as
void addNode(struct node **q, char *d)
and adjust your code accordingly:
*q = malloc(sizeof(struct node));
and so on...
When you pass struct node *q to addNode you are giving it an address for an element in your array. If you use malloc inside, then you are overwriting this variable q, which is local to the function and now points to something different, but you haven't changed your original array. Try using a pointer to pointer to node (struct node **q).
void addNode(struct node *q, char *d){
if(q == NULL)
q = malloc(sizeof(struct node));
Here's the problem.
The new value of q doesn't ever get out of the function, so your array of linked lists never gets updated.
Normally the solution here is to use a double-pointer:
void addNode(struct node **q, char *d){
if(*q == NULL)
*q = malloc(sizeof(struct node));
And call it like so:
addNode(&nodesArr[i],word);
Then, if you malloc a new node, the value in the array will be set to point to the new node.
struct node
{
int actual, estimated;
char c;
struct node *next;
} *head[4], *var[4], *trav[4];
void
insert_at_end (char c, int value, int value1)
{
struct node *temp;
temp = head[i];
var[i] = (struct node *) malloc (sizeof (struct node));
var[i]->actual = value;
//var1=(struct node *)malloc(sizeof(struct node));
var[i]->estimated = value1;
var[i]->c = c;
//printf("%d",var->estimated);
if (head[i] == NULL)
{
head[i] = var[i];
head[i]->next = NULL;
}
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
var[i]->next = NULL;
temp->next = var[i];
}
}

Resources