Delete function in linked-list - c

Do you understand why when i call the delete function here the output become an infinite loop? Without that function the code works.
int main(){
node *head = NULL;
end(&head);
begin(&head);
begin(&head);
end(&head);
begin(&head);
end(&head);
begin(&head);
delete(&head);
display(head);
return 0;
}
void delete(node **head){
node *tmp,*prev = NULL;
int num;
printf("Insert the number that you want to delete: ");
scanf("%d",&num);
tmp = *head;
if (tmp->data == num){
*head = tmp->next;
free(tmp);
return;
}
while(tmp->data!=num && tmp!=NULL){
prev = tmp;
tmp = tmp->next;
}
if(tmp == NULL){
return;
}
prev->next = tmp->next;
free(tmp);
}
Those are my other function:
void begin(node **head){
node *new;
int num;
new = malloc(sizeof(node));
if(new == NULL){
perror("malloc");
EXIT_FAILURE;
}
printf("Insert number at the beginning: ");
scanf("%d",&num);
new->data = num;
new->next = *head;
*head = new;
}
void end(node **head){
int num;
node *tmp,*new;
new = malloc(sizeof(node));
if(new == NULL){
perror("malloc");
EXIT_FAILURE;
}
printf("Insert number at the end: ");
scanf("%d",&num);
new->data = num;
tmp = *head;
if(tmp == NULL){
tmp = malloc(sizeof(node));
tmp->data = num;
tmp->next = NULL;
}
while(tmp->next!=NULL){
tmp = tmp->next;
}
new->next = NULL;
tmp->next = new;
}
void display(node *head){
node *tmp;
if(head == NULL){
printf("Empty list");
}
else{
while(tmp!=NULL){
printf("%d ",tmp->data);
tmp = tmp->next;
}
}
}

temp != NULL condition should be ahead of temp->data != num inside while loop.
Because if the temp reaches to the end of list without any match then temp will be NULL and you can't have check value(temp->data != num) for NULL pointer.

Ok i understand the problem. I forgot to add tmp = head in the else{} condition in the display() function

Related

Multiple data inside a single linked list node

Is it possible to have multiple data inside a single linked list node in C? And how do you input and access data with this?
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
char name[30];
struct node *next;
};
struct node *head, *tail = NULL;
void addNode(int data, char string) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->name[30] = string;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s", current->data, current->name);
current = current->next;
}
printf("\n");
}
int main()
{
char string1[10] = "Aaron";
char string2[10] = "Baron";
char string3[10] = "Carla";
addNode(9, string1);
addNode(7, string2);
addNode(2, string3);
printf("Original list: \n");
display();
sortList();
printf("Sorted list: \n");
display();
return 0;
}
I don't understand why my code didn't work. I was trying to make use of single linked list where it can accept/input and print/output the number and the name at the same time.
What I want it to happen is to print the number and the name.
The output should be:
Carla - 2
Baron - 7
Aaron - 9
Please read my comments marked as // CHANGE HERE.
// CHANGE HERE: accept a character array as argument
void addNode(int data, char string[]) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
// CHANGE HERE: copy char array argument to name
strncpy(newNode->name, string, 30);
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
char temp1[30];
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
// CHANGE HERE: swap the name along with data
strncpy(temp1, current->name, 30);
strncpy(current->name, index->name, 30);
strncpy(index->name, temp1, 30);
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s\n", current->data, current->name);
current = current->next;
}
printf("\n");
}

Add element linked list

#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node ** head, int n);
void display_list(node * head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
printf("Insert size of list: ");
scanf("%d",&n);
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void create_list(node **head,int n){
node *new,*tmp;
int num,i;
*head = malloc(sizeof(node));
if(*head == NULL){
printf("Memory can not be allocated.");
}
else{
printf("Insert element 1: ");
scanf("%d",&num);
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for(i=2;i<=n;i++){
new = malloc(sizeof(node));
if(new == NULL){
printf("Memory can not be allocated.");
break;
}
else{
printf("Insert element %d: ",i);
scanf("%d",&num);
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
scanf("%d", &num);
new->data = num;
new->next = NULL;
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
}
}
I don't understand why after using the add_e() function, the display_list() function gives to me only the last two number of the list. The add_e() fucntion should be add an element at the end of the list. What am i doing wrong?
Edit: Added create_list() function so you can understand better but now it says to me to add more details so I'm writing something.
In main, n is unitialized, so you'll get random/bad results.
The add_e should not use *head in the while or even do a while. The printf says "insert at beginning", which is different/simpler. This is what I've currently coded up/fixed.
You'd want to use a loop, if you [really] wanted to insert/append to the end of the list. But, the loop would still be incorrect, because you don't want to advance head when finding the end.
I've also fixed the printf for prompts and scanf
Here's a refactored/fixed version of your code with the bugs annotated:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
// NOTE/BUG: n is unitialized
#if 1
n = 5;
#endif
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void
create_list(node **head, int n)
{
node *new,
*tmp;
int num,
i;
*head = malloc(sizeof(node));
if (*head == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element 1: ");
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for (i = 2; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
else {
printf("Insert element %d: ", i);
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
fflush(stdout);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
#if 0
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
#else
if (*head == NULL)
*head = new;
else {
new->next = *head;
*head = new;
}
#endif
}
}
UPDATE:
In add_e, because I couldn't be sure if you wanted to insert at beginning of list [based on the printf] or at the end [based on the code], I created a version that is cleaned up a bit more and demonstrates both types:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_begin(node **head);
void add_end(node **head);
int
main(void)
{
int n;
node *head;
setbuf(stdout,NULL);
head = NULL;
printf("Enter initial number of list elements: ");
scanf(" %d",&n);
create_list(&head, n);
display_list(head);
add_begin(&head);
display_list(head);
add_end(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
node *cur;
if (head == NULL) {
printf("Empty list.\n");
}
for (cur = head; cur != NULL; cur = cur->next)
printf("DATA: %d\n", cur->data);
}
void
create_list(node **head, int n)
{
node *new, *tmp;
int num, i;
tmp = *head;
for (i = 1; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
printf("Insert element %d: ", i);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
if (*head == NULL)
*head = new;
else
tmp->next = new;
tmp = new;
}
}
// add_begin -- insert at before head of list
void
add_begin(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Insert element at the beginning: ");
scanf(" %d", &num);
new->data = num;
new->next = *head;
*head = new;
}
// add_end -- add to tail/end of list
void
add_end(node **head)
{
node *new;
node *tmp;
node *tail;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Append element at the end: ");
scanf(" %d", &num);
new->data = num;
new->next = NULL;
// find the tail
tail = NULL;
for (tmp = *head; tmp != NULL; tmp = tmp->next)
tail = tmp;
if (tail != NULL)
tail->next = new;
else
*head = new;
}

Linked List Insert and Delete

I'm trying to do a program that inserts and deletes students from a linked list and when I try to insert a student at the end of the list but it doesn't work. I'm pretty sur that I the function algorithm is right, but still. Anyways, here's the code:
void InsetEnd(){
stud *temp, *newnode;
char n[15];
int a;
printf("Student: \n");
printf("Name: ");
scanf("%s", n);
printf("Age: ");
scanf("%d", &a);
strcpy(newnode->name, n);
newnode->age=a;
temp=head;
while(temp!=NULL){
temp=temp->next;
}
temp = (stud *) malloc (sizeof(stud));
newnode->next = NULL;
temp->next = newnode; }
For starters the pointer newnode has indeterminate value. Thus these statements
strcpy(newnode->name, n);
newnode->age=a;
result in undefined behavior.
This loop
while(temp!=NULL){
temp=temp->next;
}
does not make sense because it is evident that after the loop the pointer temp will be equal to NULL.
And you have to change the last pointer in the list after which the new node is inserted.
The function can look at least the following way (though using the function scanf with a character array as it is used in your program is unsafe)
void InsetEnd()
{
stud *newnode;
stud **temp;
char n[15];
int a;
printf("Student: \n");
printf("Name: ");
scanf("%s", n);
printf("Age: ");
scanf("%d", &a);
newnode = ( stud * )malloc( sizeof( stud ) );
strcpy( newnode->name, n );
newnode->age = a;
newnode->next = NULL;
temp = &head;
while ( *temp != NULL ) temp = &( *temp )->next;
*temp = newnode;
}
I was able to solve the problem. It was just the allocation place in the function. I actually had to allocate memory before creating the node, which if you inverse it will not create anything and it will only display garbage.
void InsetEnd(){
stud *temp, *newnode;
char n[15];
int a;
printf("Student: \n");
printf("Name: ");
scanf("%s", n);
printf("Age: ");
scanf("%d", &a);
newnode = (stud *) malloc (sizeof(stud));
strcpy(newnode->name, n);
newnode->age=a;
temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
newnode->next = NULL;
temp->next = newnode; }
Seems like you caught your own issue. Allocating memory before trying to access or set data is essential! There are a few more things I felt like I need to mention to help you in the future.
void InsetEnd(stud *head) { // pass head pointer, becomes local pointer so its not overriden
if (!head)
return; // dont do anything if list does not exist
stud *newnode; // no need for tmp anymore
char n[15] = ""; // initialize
int a;
printf("Student: \n");
printf("Name: ");
scanf("%14s", n); // take only 14 chars, leaving the 15th '\0' or you'll have problems reading long names after
printf("Age: ");
scanf("%d", &a);
newnode = calloc(1,sizeof(*newnode)); // use calloc to avoid junk
// ^ type casting a return of void* is not necessary in c
strcpy(newnode->name, n);
newnode->age=a;
while(head->next) // NULL is pretty much false
head=head->next;
// no need to set newnode next to null, its already null from calloc
head->next = newnode;
}
Hope this helps!
I will try to explain it from the following example
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class Node {
public:
double data; // data
Node* next; // pointer
};
class List {
public:
List(void) { head = NULL; } // constructor
~List(void); // destructor
bool IsEmpty() { return head == NULL; } //boş kontrolü
Node* InsertNode(int index, double x); //node ekle
int FindNode(double x); //node bul
int DeleteNode(double x); //node sil
void DisplayList(void); //liste görüntüle
private:
Node* head; //baş kısmı
};
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = new Node;
newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else{
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
int List::FindNode(double x) {
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
currNode = currNode->next;
currIndex++;
}
if (currNode) return currIndex;
return 0;
}
int List::DeleteNode(double x) {
Node* prevNode = NULL;
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode) {
if (prevNode) {
prevNode->next = currNode->next;
delete currNode;
}
else {
head = currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
void List::DisplayList()
{
int num = 0;
Node* currNode = head;
while (currNode != NULL)
{
printf("\n%lf",currNode->data);
currNode = currNode->next;
num++;
}
printf("\nNumber of nodes in the list: %d",num);
}
List::~List(void) {
Node* currNode = head, *nextNode = NULL;
while (currNode != NULL)
{
nextNode = currNode->next;
// destroy the current node
delete currNode;
currNode = nextNode;
}
}
int main(int argc, char** argv) {
List list;
list.InsertNode(0,5.4); //başarılı
list.InsertNode(1,6.5); //başarılı
list.InsertNode(-2,5.5);//başarsız
list.InsertNode(2,10.0);//başarılı
list.DisplayList();
list.DeleteNode(5.4);
list.DisplayList();
return 0;
}
Now edit node part
class Node {
public:
int no;
char name[15];
char surname[15];
int age;
Node* next;
};
and insert function. Flow chart is here.
Node* List::InsertNode(int index, int no,char name[15],char surname[15],int age){
if (index < 0) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = new Node;
newNode->no = no;
strcpy_s(newNode->name, name);
strcpy_s(newNode->surname, surname);
strcpy_s(newNode->age, age);
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}

when i am selecting delete option before inserting any value in linked list i am getting segmentation fault error

#include<stdio.h>
#include<malloc.h>
typedef struct nnode
{
int value;
struct nnode *next;
} node;
void insert(node **ptr, int val) //for insertion
{
node *temp, *temp2;
temp = *ptr;
if (*ptr == NULL)//if list is empty
{
temp = (node *) malloc(sizeof (node));
temp->value = val;
temp->next = NULL;
*ptr = temp;
}
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
temp2 = (node *) malloc(sizeof (node));
temp2->value = val;
temp2->next = NULL;
temp->next = temp2;
}
}
void display_node(node **ptr)
{
node *temp;
temp = *ptr;
while (temp != NULL)
{
printf("%d--->", temp->value);
temp = temp->next;
}
printf("null");
}
void de_node(node **ptr)
{
int val;
node *temp, *temp2;
temp = *ptr;
temp2 = temp->next;
printf("\nenter the value to be deleted\n");
scanf("%d", &val);
if ((*ptr) == NULL)
{
printf("list is empty .....");
return;
}
else if ((*ptr)->value == val)
{
*ptr = (*ptr)->next;
free(temp);
}
else
{
while ((temp->next->value != val)&&(temp2->next != NULL))
{
temp = temp->next;
temp2 = temp->next;
}
if (temp2->next == NULL)
{
printf("\nvalue not found");
}
if (temp->next->value == val)
{
temp->next = temp2->next;
free(temp2);
}
}
}
void main()
{
node *head = NULL;
int ch;
int n;
while (1)
{
printf("\nenter your choice\n");
printf("1.ADD ELEMENT\n");
printf("2.DELETE ELEMENT\n");
printf("3.DISPLAY LIST\n");
printf("4.EXIT\n");
scanf("%d", &ch);
switch (ch)
{
case 1:printf("\n enter data \n");
scanf("%d", &n);
insert(&head, n);
display_node(&head);
break;
case 2:de_node(&head);
display_node(&head);
break;
case 3:display_node(&head);
break;
case 4:exit(0);
}
}
}
my problem is before inserting anything in list when i am deleting element
i.e when i am trying to delete an element when list is empty
then according to my code it should print "list is empty....."
but instead it is giving segmentation fault error.
The problem is here:
temp = *ptr;
temp2 = temp->next;
You have temp set to *ptr, but you haven't yet checked if *ptr is NULL. So when you try to dereference it with temp->next, you get the segfault.
Since you're not using temp2 until later, move this line right before your while loop:
temp2 = temp->next;

Insertion at end in circular linked list not working in C

Please point out the error in the code.
The function insertatend() inserts for the first time but not again.
I'm trying to insert a node at the end of a circular linked list, but after inserting an element for the first time, it gets stuck in the while loop if we try to enter data again.
struct node {
int data;
struct node *next;
};
typedef struct node node;
node *head = NULL;
node *insertatend(node *head, int value)
{
node *temp, *p;
p = head;
temp = (node *)malloc(sizeof(node));
temp->data = value;
temp->next = head;
if (head == NULL)
{
head = temp;
}
else
{
while (p->next != head)
p = p->next;
p->next = temp;
}
return head;
}
void display(node *head)
{
node *p = head;
if (head == NULL)
{
printf("\nlinked list is empty\n");
return;
}
while (p->next != head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
int ch = 1, value;
while (ch)
{
printf("1.Insert 2.Display");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("enter an element:");
scanf("%d", &value);
head = insertatend(head, value);
break;
case 2:
display(head);
break;
}
}
return 0;
}
I think the mistake is here:
temp->next=head;
if(head==NULL){
head=temp;
}
When you enter your first element, head is null. So temp->next is set to NULL and head is set to temp.
When you enter your second element, it does this:
else{
while(p->next!=head)
p=p->next;
p->next=temp;}
Where p->next is null, so you will never have the situation that p->next == head and you will always be in the loop!
Edit:
So the solution aproach would be to change it to:
if(head==NULL){
head=temp;
}
temp->next=head;
Edit: second mistake in the display function: the loop doesn't print the last element. I just tested it and it is working fine.
So the complete code woud look like:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node node;
node *head = NULL;
node *insertatend(node *head, int value)
{
node *temp, *p;
p = head;
temp = (node *)malloc(sizeof(node));
temp->data = value;
if (head == NULL)
{
head = temp;
}
else
{
while (p->next != head)
p = p->next;
p->next = temp;
}
temp->next = head;
return head;
}
void display(node *head)
{
node *p = head;
if (head == NULL)
{
printf("\nlinked list is empty\n");
return;
}
do
{
printf("%d ", p->data);
p = p->next;
} while (p != head);
printf("\n");
}
int main()
{
int ch = 1, value;
while (ch)
{
printf("1.Insert 2.Display");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("enter an element:");
scanf("%d", &value);
head = insertatend(head, value);
break;
case 2:
display(head);
break;
}
}
return 0;
}
Alternate version, using tail pointer instead of head pointer, for faster appends.
#include <stdlib.h>
#include <stdio.h>
struct node {
struct node *next;
int data;
};
typedef struct node node;
node *insertatend(node *tail, int value)
{
node *p;
p = malloc(sizeof(node));
p->data = value;
if(tail == NULL){
p->next = p;
} else {
p->next = tail->next;
tail->next = p;
}
return p;
}
void display(node *tail)
{
node *p = tail;
if (p == NULL)
{
printf("\nlinked list is empty\n");
return;
}
do{
p = p->next;
printf("%d ", p->data);
}while(p != tail);
printf("\n");
}
int main()
{
node *tail = NULL;
int i;
for(i = 0; i < 8; i++)
tail = insertatend(tail, i);
display(tail);
return 0;
}

Resources