Linked list insert end node in C - c

I'm currently learning about linked list in C and trying to write a function to insert a node at the end and then print all the data.
At first my function did not work (only 1 2 are printed)
struct node {
int data;
struct node *link;
};
void add_end(struct node *head, int a){
struct node *current, *temp;
current = head;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = a;
temp->link = NULL;
while(current != NULL){
current = current->link;
}
current = temp;
};
int main()
{
struct node *head;
head = (struct node *)malloc(sizeof(struct node));
head->data = 1;
head->link = NULL;
struct node *current;
current = (struct node *)malloc(sizeof(struct node));
current->data = 2;
current->link = NULL;
head->link = current;
add_end(head, 3);
current = head;
while(current != NULL){
printf("%d\n", current-> data);
current = current->link;
}
return 0;
}
After a while fixing it worked ( 1 2 3 are printed )
void add_end(struct node *head, int a){
struct node *current, *temp;
current = head;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = a;
temp->link = NULL;
while(current->link != NULL){
current = current->link;
}
current->link = temp;
};
Can anyone tell me why the first one did not work pls. I thought they are the same because in the first version: current is the link of the last node which is the address of the next node (null) and in the second version: current->link is the link of the last node, which is the address of the next node (null) as well.

Once current is NULL you have already passed the last node in the list, and current is a NULL pointer.
Assigning to it will not add the node to the list, it will just reassign current to no longer be a NULL pointer, but the last nodes link will not have been modified.
With the second function you find the actual last node in the list, and append the new node to the end.

Related

Can't insert a node at the beginning of a linked list using a void function

I m trying to insert a newNode at the beginning of a linked list in C language. I have tried other methods such as returing the newNode from the insertAtBeginnning function and then setting the head as that newNode in the main function & that works fine. But what I want to do is use a void function for the case and change the head there itself which is not working.
Here's the complete code :
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void linkedListTraversal(struct Node *ptr)
{
while (ptr != NULL)
{
printf("element: %d\n", ptr->data);
ptr = ptr->next;
}
}
void insertAtBeginning(struct Node *head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = head;
head = newNode;
}
void insertAtIndex(struct Node *head, int data, int index)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp = head;
int i = 0;
while (i < index - 1)
{
temp = temp->next;
i++;
}
newNode->data = data;
newNode->next = temp->next;
temp->next = newNode;
}
void insertAtEnd(struct Node *head, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode;
newNode->data = data;
newNode->next = NULL;
}
void insertAfterNode(struct Node *previous, int data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = previous->next;
previous->next = newNode;
}
int main()
{
struct Node *head;
struct Node *second;
struct Node *third;
struct Node *fourth;
// Allocate memory for the nodes of the linkedLists in the heap
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));
// Link first and second nodes
head->data = 12;
head->next = second;
// Link second and third nodes
second->data = 98;
second->next = third;
// Link third and fourth nodes
third->data = 38;
third->next = fourth;
// Terminate the linkedList at the fourth node
fourth->data = 37;
fourth->next = NULL;
printf("Linked list before insertion\n");
linkedListTraversal(head);
insertAtBeginning(head, 20);
// insertAtIndex(head, 22, 3);
// insertAtEnd(head, 110);
// insertAfterNode(second, 27);
printf("Linked list after insertion\n");
linkedListTraversal(head);
return 0;
}
Here i have also used other cases of insertion in linked list and all are working fine instead of just insertAtBeginning function :(
Any help will be greatfull.
head is the entry point for your list. Inserting an element at the beginning should make head point to this new element. To do it from a void function, you have to pass the address of head so that head is modified by the function:
void insertAtBeginning(struct Node **head, int data)
{
struct Node *newNode = malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
The call to the function will therefore be:
insertAtBeginning(&head, 20);
Another solution would be to have the function return the new address of head.
PS: we don't cast the return from malloc in C and we should check that it succeeded.

Adding a node to the head of the linked list

I would like to add a node in a sorted linked list based on the number. This is the struct:
struct node {
int number;
struct node *next;
}
I am able to add to the sorted linked list correctly but can't get it to change head.
Unfortunately I can't change the format of the function declaration so this is my function:
int create(struct node *head, int number) {
struct node *newNode = malloc(sizeof(struct node));
newNode->number = number;
struct node *current = head;
if (current->number == -1) {
newNode->next = NULL;
*head= *newNode;
return 1;
}
//Checking if head's number is bigger than init
if (current->number > number) {
newNode->next = current;
*head = *newNode;
} else {
while(current->next != NULL && (current->number <= number)) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
return 1;
}
the call to the function is (Note I also can't change this):
struct node *list;
list = initializeList();
int num;
num = create(list, 5);
num = create(list, 1);
After the second call, the list should be 1->5. But it becomes 1->1->1->1->.....
Edit: Code to Initialize list:
struct node * initializeList() {
struct node *head;
head = malloc(sizeof(struct node));
head->next = NULL;
head->number = -1;
return head;
}
I made a few edits to the create function to fix the problem.
First, if the head of the list has number == -1 then no new node should be allocated, since you are just replacing the number.
Second, if you need to insert a node, the previous node needs to know where to the next node goes, so you can't just replace the previous node with the new node. You need to either point the previous node to the new node and point the new node to the displaced node; or you can copy the current node into the new node, and put the number for the new node into the current, and point it to the new node. The second works better here, since it does not require changing the head (which we can't do if it needs to go at the front).
int create(struct node *head, int number) {
struct node *current = head;
if (current->number == -1) {
current->number = number;//just replace the number, no need for anything else
return 1;
}
//allocate only if we must insert
struct node *newNode = malloc(sizeof(struct node));
//no longer need to check if head
while(current->next != NULL && (current->number <= number)) {
current = current->next;
}
if(current->next == NULL && current->number < number) {//check if number needs to go at the end
current->next = newNode;
newNode->next = NULL;
newNode->number = number;
} else {
*newNode = *current;//newNode will go after current, but with current's values
current->number = number;//replace current with the number to "insert" it
current->next = newNode;//point to the next node
}
return 1;
}
assign an index value to the node and shift the other elements by one. I mean you can add one to the each value of the other element and make in iterate in a loop.

C: Problems with Reversing a linked list

I'm writing a program to create a linked list(a node), then reverse it. The linked list contains data and the address of the next.
typedef struct node{
int data;
struct node *next;
}node;
Firstly, I create the linked list.
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
After that, i create a function to print these data. (i called it PrintNode)
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
Finally, a function created to reverse the linked list.
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
It's my full program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
struct node *Insert_value(int dataInput,node* head);
struct node * Reversing(node **head);
void PrintNode(node *head);
main()
{
node *head = NULL;
int i=0,dataInput;
while(i!=5)
{
printf("input your elements: ");
scanf("%d",&dataInput);
head = Insert_value(dataInput,head);
i++;
}
PrintNode(head);
head = Reversing(&head);
PrintNode(head);
}
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
void PrintNode(node* head)
{
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
After debugging lots of times, I know that these functions are fine. However, after the reverse function, the address of the next node of the head variable is NULL. Can you explain and give me some pieces of advice?
The one line change that will solve your problem will be (you visualized it a bit wrong).
current->next =previous;
in place of
previous->next = current;
Your code will blowup for single element linked list. Add a proper check for that in the function Reversing(). In case there is single element first->next will be NULL. But you wrote first->next->next which will be undefined behavior in case first->next is NULL.
In earlier case you were just creating a linked list in Reversing() with the links unchanged but head was pointing to the last node. So the next of it was NULL.
Modify Reversing such that new nodes are appended at the end. When going through the list, you need to save the next node ahead of time (node *next = current->next)
struct node* Reversing(node **head)
{
node *current = *head;
node *reverse = NULL;
while(current)
{
node *next = current->next;
if(!reverse)
{
reverse = current;
reverse->next = NULL;
}
else
{
current->next = reverse;
}
reverse = current;
current = next;
}
return reverse;
}

Inserting a node before a given node in doubly linked list

I am trying to insert a node before a given node. But I am not able to get the required output.
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node* prev;
struct node* next;
};
void insert_beg(struct node** head, int new_data){
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = new_data;
if(*head == NULL){
temp->next = *head;
temp->prev = NULL;
*head = temp;
}
else{
temp->next = *head;
(*head)->prev = temp;
*head = temp;
}
}
void insert_before(struct node* next_node,int new_data){
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp->data = new_data;
if(next_node == NULL)
printf("Invalid!!!!");
temp->prev = next_node->prev;
temp->next = next_node;
next_node->prev = temp;
if(temp->prev!=NULL)
temp->prev->next = temp;
}
void printList(struct node* head){
if(head == NULL)
printf("The list is empty\n");
else
{
while(head!=NULL){
printf("%d\n",head->data);
head = head->next;
}
}
}
int main(){
struct node* head = NULL;
printList(head);
insert_beg(&head,10);
insert_beg(&head,20);
insert_before(head,70);
insert_beg(&head,30);
printList(head);
}
Here I am trying to insert a node(with data = 70) before 20.
Output: 30,20,10
Expected Output: 30,70,20,10
When you call insert_before, if the given node is the head, then the new node will be the new head. So you need to pass the the address of head in order to modify it.
What you have right now looks like this:
head
|
v
------ ------ ------
- 30 - ---> - 20 - ---> - 10 -
------ <--- ------ <--- ------
^
------ |
- 70 - ---------|
------
To fix this, include the address of head in the parameters to insert_before.
void insert_before(struct node **head, struct node *next_node, int new_data){
struct node* temp = malloc(sizeof(struct node)); // don't cast the return value of malloc
temp->data = new_data;
if(next_node == NULL)
printf("Invalid!!!!");
temp->prev = next_node->prev;
temp->next = next_node;
next_node->prev = temp;
if(temp->prev!=NULL) {
temp->prev->next = temp;
} else {
*head = temp;
}
}
Then call it like this:
insert_before(&head,head,70);
You are doing everything right.But you are missing one thing In insert_before if the passed parameter next_node is head then you will be inserting a node before head. Therefore you have to make this newly added node a head.

Inserting In a Doubly LinkedList

I am trying to insert into a doubly linked list. I am then trying to print the list in both forward and reverse direction. I have created a head node and I am trying to insert another one, but I am unable to do so. The program shows a runtime error.
Please find my code below. Any help would be appreciated.
#include<stddef.h>
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
struct node *prev;
};
void insertAfter(struct node *node, int new_data){
if (node == NULL)
{
printf("the given previous node cannot be NULL");
return;
}
struct node* new_node = (struct node*)malloc(sizeof(struct node));
node->data = new_data;
node->next = new_node;
new_node->prev = node;
new_node->next - node->next;
if(new_node->next!=NULL)
new_node->next->prev = new_node;
}
void printlist(struct node *node){
struct node *last;
printf("Traversal in forward direction\n");
while(node!=NULL){
printf("%d\n",node->data);
last = node;
node=node->next;
}
printf("Traversal in backward direction\n");
while(last!=NULL){
printf("%d\n",last->data);
last=last->prev;
}
}
int main()
{
struct node *head;
struct node *tail;
head->data = 5;
tail->data = 10;
head->next = tail;
head->prev = NULL;
tail->next = NULL;
insertAfter(head, 8);
printf("\n Created DLL is: ");
printlist(head);
return 0;
}
There are several problems here.
First, as pointed out by #Igor, you are not allocating any memory for your head and tail nodes. You should also set tail->prev = head.
Second, the order in which insertAfter sets the link pointers causes node->next to be overwritten before it is used in setting new_node->next. This causes new_node->next to point back to new_node instead of to whatever was following node. You should set new_node->next and new_node->prev before you modify node. It also appears that you have used a minus sign instead of an equals in the "assignment" of new_node->next.
Third, in printlist, you should initialize last to NULL in case the list is empty; otherwise, you will attempt to walk the list backwards from an undefined starting (ending) point.
You want new_node->next to be the same as new_node?
if not, you'd better swap these two lines, in InsertAfter:
node->next = new_node;
new_node->next - node->next;
You need to allocate memory for your pointers head and tail.
int main()
{
struct node *head;
struct node *tail;
head = malloc(sizeof(struct node)); //allocating memory to head
tail = malloc(sizeof(struct node)); //allocating memory to tail
head->data = 5;
tail->data = 10;
head->next = tail;
head->prev = NULL;
tail->next = NULL;
insertAfter(head, 8);
printf("\n Created DLL is: ");
printlist(head);
return 0;
}
Also, never cast the return value of malloc, therefore change:
struct node* new_node = (struct node*)malloc(sizeof(struct node));
to
struct node* new_node = malloc(sizeof(struct node));

Resources