Inserting In a Doubly LinkedList - c

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));

Related

Segmentation Fault In Linked List Append

I have been using linked list and I have used the following code for append function which i wrote in a new file and it works perfectly but when I copy it my main code it gives segmentation fault at while(current->next != null) . It does not give any warning while compiling so I don't know whats the issue here.
// Linked List Node for Reading Comments
struct Node{
char value;
struct Node *next;
};
void append(struct Node * headNode, char newElement){
struct Node *newNode = malloc(sizeof(struct Node)); //Dynamically Allocating Memory for New Node
struct Node *current = headNode; //Creating A Node to traverse the linked list
newNode->value = newElement; //Assigning the values of newNode to the given value
newNode->next = NULL; //Setting next value to be null since its the last node
if (headNode == NULL){ //Checking if headnode is empty
headNode = newNode; //Assigning headnode and tailnode to be newnode
}
else {
while(current->next != NULL){ //Traversing through the linked list
current = current->next;
}
current->next = newNode; //Setting tailnode's next to be newnode
}
}
void printLinkedList(struct Node* headNode){
while(headNode != NULL){
fprintf(stderr,"%c",headNode->value);
headNode = headNode->next;
}
}
If anyone can comment on this please do.
Your code does not allow to add a node to an empty list. If you try and did not initialise your head pointer on the calling side, you may get such behavior.
For instance, in main you could have:
struct Node* head; // not initialised
append(head, 'a');
printLinkedList(head);
These are then the issues:
If head happens to be not NULL, then the else block will kick in and the current pointer will reference some unintended memory address.
append will not change the head variable of main. It will only modify a local variable that happens to have a similar name (headNode).
To correct, pass the address of head to the append function, and let append deal with this accordingly:
void append(struct Node ** headNode, char newElement) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *current = *headNode;
newNode->value = newElement;
newNode->next = NULL;
if (*headNode == NULL) {
*headNode = newNode;
} else {
while(current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
}
Note the additional * wherever headNode occurs. In main:
struct Node* head;
append(&head, 'a');
printLinkedList(head);

Linked list insert end node in 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.

how to implement linked list

#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void push(struct Node** head_ref, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = (*head_ref);
new_node->prev = NULL;
if ((*head_ref) != NULL)(*head_ref)->prev = new_node;
(*head_ref) = new_node;}
void append(struct Node** head_ref, int new_data){
/* 1. allocate node */
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
struct Node* last = *head_ref; /* used in step 5*/
/* 2. put in the data */
new_node->data = new_data;
/* 3. This new node is going to be the last node, so
make next of it as NULL*/
new_node->next = NULL;
/* 4. If the Linked List is empty, then make the new
node as head */
if (*head_ref == NULL) {
new_node->prev = NULL;
*head_ref = new_node;
return;}
/* 5. Else traverse till the last node */
while (last->next != NULL)
last = last->next;
/* 6. Change the next of last node */
last->next = new_node;
/* 7. Make last node as previous of new node */
new_node->prev = last;
return;}
void insertAfter(struct Node* prev_node, int new_data){
/*1. check if the given prev_node is NULL */
if (prev_node == NULL) {
printf("the given previous node cannot be NULL");
return;}
/* 2. allocate new node */
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
/* 3. put in the data */
new_node->data = new_data;
/* 4. Make next of new node as next of prev_node */
new_node->next = prev_node->next;
/* 5. Make the next of prev_node as new_node */
prev_node->next = new_node;
/* 6. Make prev_node as previous of new_node */
new_node->prev = prev_node;
/* 7. Change previous of new_node's next node */
if (new_node->next != NULL)
new_node->next->prev = new_node;}
void printList(struct Node* node){
struct Node* last;
printf("\nTraversal in forward direction \n");
while (node != NULL) {
printf(" %d ", node->data);
last = node;
node = node->next;}
printf("\nTraversal in reverse direction \n");
while (last != NULL) {
printf(" %d ", last->data);
last = last->prev;
}}
void sortedInsert(struct Node** head, int new_data) {
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = NULL;
struct Node* temp;
if ((*head) == NULL || (new_node->data) > (*head)->prev->data) {
append(head, new_data);
return;
}
if ((new_node->data) < ((*head)->data)) {
push(head, new_data);
return;
}
temp = (*head)->next;
while ((temp->data) < (new_node->data)) {
temp = temp->next;
}
insertAfter(head, new_data);
}
int main() {
struct Node* head = NULL;
sortedInsert(&head, 0);
sortedInsert(&head, 9);
sortedInsert(&head, 4);
sortedInsert(&head, 3);
sortedInsert(&head, 34);
sortedInsert(&head, 15);
printf("\n Created Linked list is: ");
printList(head);
return 0;}
I am trying to write a C program where data must be inserted in a ordered way (smaller to higher)
When I run the code program gives error due to the note:
expected 'struct Node *' but argument is of type 'struct Node **'
how can I fix this problem , I have looked up to the other solutions such as : What does the warning - expected ‘struct node **’ but argument is of type ‘struct node **’ mean?
but those couldnt resolve my issue.
Any help is appreciated
insertAfter(head, new_data);
how can I fix this problem
You forgot to dereference struct Node** head as you correctly did at other places in the function sortedInsert; to get the argument type right, it would be insertAfter(*head, new_data).
But still the insertion logic isn't quite right; here's a corrected version:
void sortedInsert(struct Node** head, int new_data) {
// new node is allocated in append(), push() or insertAfter()
struct Node* temp;
if ((*head) == NULL || new_data < (*head)->data) {
push(head, new_data);
return;
}
temp = *head;
while (temp->next && temp->next->data < new_data) {
temp = temp->next;
}
insertAfter(temp, new_data);
}
When you are using the functions you declared you should pass a reference (address) to the head not the head itself as this what your code requires.
As an example, use append(&head, 3) instead of append(head, 3)

Related to pointers in C

void pushathead(struct Node* head, int data){
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = data;
new_node->next = head;
head = new_node;
}
void pushathead(struct Node** head, int data){
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = data;
new_node->next = (*head);
(*head) = new_node;
}
Can anyone explain the difference between the two methods, and which one should be used for implementation?
The first implementation accepts a pointer argument to the head of your linked list.
The second implementation accepts a pointer to a pointer to the head of your linked list.
Can you tell why that might be important?
You want to use the second one, otherwise you will lose any reference to the new node being created.
In other words, the first implementation is just modifying a local copy of head, the last line head = new_node; is meaningless, doing effectively nothing because it's working on a local value. The second implementation will modify a pointer on the outside.
First will be called like this:
Node *head = NULL; // declared somewhere
pushathead( head, 1 );
And the second will be called like this:
Node *head = NULL;
pushathead( &head, 1 );
Using the address-of operator here is a big hint that head is going to be modified, and that's what you want.
I'd go for a third choice:
struct Node* pushathead(struct Node* head, int data){
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = data;
new_node->next = head;
return new_node;
}
and use it like this:
Node *list = NULL; // declared somewhere
list = pushathead( list, 10 );
list = pushathead( list, 20 );

Linked List C: add node to beginning, unexpected '0' value

I am trying to add a new node to the end of a linked list, I am able to add something, but when I print it out the node has a value of '0'. I thought this might be happening because I may have neglected to initialise a variable somewhere, or forgot to allocate memory said variable. but I can't get it to work.
Here is my source code:
my Linked List/struct:
#include<stdio.h>
typedef char DATA;
struct Node {
DATA d;
struct Node *next;
};
my printList function:
void printList(struct Node **head) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *temp;
temp = *head;
printf("Linked list:");
while (temp->next != NULL) {
printf( " \n %d ", temp->d);
temp = temp->next;
}
printf("\n");
}
my insertNodeAtEnd to end function:
// inset data at end
void insertNodeAtEnd(struct Node *head) {
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *currentNode, *temp;
temp = newNode;
currentNode = newNode;
printf("Enter a Node to insert at the end of the list \n");
scanf("%s", &newNode->d);
newNode->next = NULL;
if (head == NULL) {
head = newNode;
currentNode = newNode;
} else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
}
and my main():
int main() {
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers");
for (i = 0; i < 3; i++) {
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
scanf("%d", &temp->d);
temp->next = newNode;
temp = temp->next;
}
insertNodeAtEnd(head);
printList(&head);
return 0;
sorry for any messy code, I'm still reasonably new at this
Well, you have a couple of mistakes. Firstly, you need to add
temp->next = NULL;
before line insertNodeAtEnd(head);. The reason your code might work without this line is probably because your compiler initializes the pointer to NULL by default. For example in GCC you program is crashing without that line.Second problem is that you are defyning DATA type as a char, but reading it as int. It may cause crashing your application if processor working with big-engian addresses. You should change it to
typedef int DATA;
and also change
scanf("%s", &newNode->d);
to
scanf("%d", &newNode->d);
After that, change
while(temp->next!=NULL)
to
while(temp!=NULL)
because otherwise you are missing the last element. Then, you need to reorder a loop a little bit. This is the full working code with all fixes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef int DATA;
struct Node
{
DATA d;
struct Node *next;
};
void printList(struct Node **head)
{
struct Node *newNode;
struct Node *temp;
temp = *head;
printf("Linked list:");
while(temp!=NULL)
{
printf( " \n %d ", temp->d);
temp = temp->next;
}
printf("\n");
}
// inset data at end
void insertNodeAtEnd(struct Node **headPointer)
{
struct Node *head = *headPointer;
struct Node *newNode = malloc(sizeof(struct Node));
struct Node *currentNode, *temp;
temp = newNode;
currentNode = newNode;
printf("Enter a Node to insert at the end of the list \n");
scanf("%d", &newNode->d);
newNode->next = NULL;
if(head == NULL)
{
head = newNode;
currentNode = newNode;
}
else
{
temp = head;
while(temp->next!= NULL)
{
temp = temp->next;
}
temp->next = newNode;
}
*headPointer = head;
}
int main()
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
struct Node *head = newNode;
struct Node *temp = newNode;
head->d = 1;
int i = 0;
printf("Enter 3 numbers: ");
for(i = 0; i < 3; i++)
{
if(i){
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
temp->next = newNode;
temp = temp->next;
scanf("%d", &temp->d);
}else{
scanf("%d", &temp->d);
}
}
temp->next = NULL;
insertNodeAtEnd(&head);
printList(&head);
return 0;
}
UPDATE
I added a two more fixes. as #BLUEPIXY pointed out, there are a few more OP's mistakes. I've already spotted them, but I didn't fix it because they were not essential to what causes OP's problem. But, anyway, the mistakes are following:
Firstly, if the list is empty, function insertNodeAtEnd will not update pointer to the list because you are passing pointer to head of the list instead of pointer of a pointer to the head. It can be fixed by adding ** to the function argument type.
Secondly, you don't need to allocate memory while printing a list. You obviously just copied the code to each function, even to functions which doesn't require inserting nodes (like printList).
The above script is updated script including these two fixes.

Resources