Adding nodes to end of a linked list in C - c

The code I have is adding nodes to head but I want them added to tail. I tried pointing head to next node to null but it stops since the next node is null
if(head==NULL)
{
head=node;
}
else
{
node->next=head;
node->prev=NULL;
head->prev=node;
head=node;
}
printf("The node is inserted to linked list succesfully. \n\n");
printMenu();

You need to keep a pointer to your list's tail, and then adding an element may look like:
node -> next = NULL;
tail -> next = node;
node -> prev = tail;
tail = node;

You need to go to the end of the list first:
if(head==NULL)
{
head=node;
}
else
{
struct nodetype *p = head;
while (p->next)
p = p->next;
p->next = node;
node->prev = p;
}

// Create new node
struct nodeType *newNode = (struct nodeType *)malloc(sizeof(struct nodeType));
// Singly-linked list and new node is end of the list so the next pointer is NULL
newNode->next = NULL;
if(head==NULL){
// If head is not assigned
head = newNode;
}
else{
// Assign the next pointer in the current node to the new node
current->next = newNode;
}
// Update the current pointer to point to the newNode
current = newNode;
where head and current is,
struct nodeType *head, *current;
If the current pointer does not point to the end of the list you can iterate over the list to the end with the following line and then start appending to the linked-list:
for(current = head; current->next != NULL; current = current->next);

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

how to insert node in Circular Linked list in C

Can someone explain the 'while part' of the code?- in the main() head is declared as struct node pointer initialized with value NULL. and a node is inserted by calling function = push(&head,12)
void push(struct Node **head_ref, int data)
{
struct Node *ptr1 = (struct Node *)malloc(sizeof(struct Node));
struct Node *temp = *head_ref;
ptr1->data = data;
ptr1->next = *head_ref;
if (*head_ref != NULL)
{
while (temp->next != *head_ref)
temp = temp->next;
temp->next = ptr1;
}
else
ptr1->next = ptr1; /*For the first node */
*head_ref = ptr1;
}
Can someone explain the 'while part' of the code?
The while() part (also described in section 2.) below.) is to look for the node which points to the current head node so that the new node can be inserted just before it. While in the loop, notice that as nodes are found, and they are not yet the head node, they are incremented so as to prepare for the insertion when head node is finally located.
The last expression in the routine:
*head_ref = ptr1;
Is to handle the case described by section 1.) in the general steps below.
General approach for the following initial conditions:
Linked List is empty:
a) since new_node is the only node in CLL, make a self loop.
new_node->next = new_node;
b) change the head pointer to point to new node.
*head_ref = new_node;
New node is to be inserted just before the head node:
(a) Find out the last node using a loop.
while(current->next != *head_ref)
current = current->next;
(b) Change the next of last node.
current->next = new_node;
(c) Change next of new node to point to head.
new_node->next = *head_ref;
(d) change the head pointer to point to new node.
*head_ref = new_node;
New node is to be inserted somewhere after the head:
(a) Locate the node after which new node is to be inserted.
while ( current->next!= *head_ref &&
current->next->data data)
{ current = current->next; }
(b) Make next of new_node as next of the located pointer
new_node->next = current->next;
(c) Change the next of the located pointer
current->next = new_node;
Details and implementation for doing this are shown in this example code

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

Delete last node of single linked list using tail pointer

I'm creating a singly linked list in C which has head and tail pointers where the head pointer points to starting node of SLL and tail pointer points to the last node of SLL. I don't want to traverse till the end of the list using the head pointer to delete the node. Is there a way so that I can use the tail pointer to delete the last element of SLL?
Following is node addition function. head and tail are initiated NULL.
void add_node_last(Node** head, Node** tail, int data) {
Node* new_node = (Node *) malloc(sizeof(Node));
new_node -> data = data;
new_node -> ptr = NULL;
if(*head == NULL && *tail == NULL) {
*head = new_node;
*tail = new_node;
return;
}
(*tail) -> ptr = new_node;
*tail = new_node;
}
To delete the first node, the following function is used:
void del_first(Node **head) {
if(*head == NULL) {
return;
}
*head = (*head) -> ptr;
free(*head);
}
You can free the node's memory, but only once. After the first removal, your tail pointer, and the ptr of the second to last node, will be invalid pointers. In order to make sure both pointers are always correct you either need to traverse the entire list or make it a doubly linked list.
That's a long way of saying no (thanks to #stark).
in order for this to work without making it a doubly linked list, you could have the tail's *next pointer point to the head of the list, then traverse through it till you reach the node before the tail. once there you can NULL its *next pointer which would essentially detach the original tail from the list. you would then set the tail to the current node, then finally free the original tail.
void del_last(Node **head, Node **tail) {
struct node *new_head = *head;
struct node *current = *tail;
current->next = head;
while(current-> != *tail) //getting the node right before the original tail
{
current = current->next
}
current->next = NULL; //detaches original tail form list
free(**tail); //gets rid of original tail
**tail = current; // sets current node to tail pointer
}

Linked list troubles list not linking to head pointer

I have been having trouble with this linked list specifically it seems like my head pointer is not linking to the rest of my list and I am confused as to why it is not. Where I insert my head pointer by pointer by reference it is not connected to the linked list referenced in main. unless the list is not linked together in the main function and I am missing something.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
} Node;
typedef Node * Nodeptr;
void printlist (Node * head){
Node * n = head;
while(n != NULL){
printf("%d\n",n ->number);
n = n ->next;
}
}
void sumlist (Node * head){
Node * n = head;
int sum;
while(n != NULL){
sum = n ->number +sum;
n = n ->next;
}
printf("the total of all numbers in this list is %d",sum);
}
search(head){
}
int main(){
int i =0;
Nodeptr head=NULL;
if((head = malloc(sizeof(Node))) == NULL)
return 0;
head->number =rand()%50+50;
head ->next = malloc(sizeof(Node));
int n;
Nodeptr newnode = NULL;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
}
printlist(head);
sumlist(head);
return 0;
}
The error is that you are linking everything as next of head
head -> next = newnode;
You need to use a pointer that gets updated:
Nodeptr newnode = NULL;
Nodeptr last = head;
for(n=0;n<99;n++)
{
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
last -> next = newnode;
last = last->next;
}
You should also change this:
head ->next = malloc(sizeof(Node)); // otherwise you will lose this element.
into
head ->next = NULL;
You execute these steps in a loop:
newnode = malloc(sizeof(Nodeptr));
newnode->number = rand()%50+50;
newnode->next =NULL;
head -> next = newnode;
You are setting the newnode->next to point to null, and head->next to point to newnode.
This means, each time through the loop your head gets a new next, and that's it.
Effectively, each time you pass through the loop you drop the previous newnode on the floor, and link to a new one. At the end, you'll have head pointing to 1 node, and you'll have 98 nodes dropped on the floor that you can't reach.
You need to either maintain a "tail" pointer, or a copy of "head", and set head or tail or something to the most recent value of newnode. Then, you can set tail->next = newnode; tail = newnode; which will continually extend your list, rather than overwriting the same head->next each time.

Resources