search and delete a node from linked list - c

I am writing a simple dictionary program using linked list. I want to search a word in the dictionary and delete it. I've wrote the code, but I think It's more time consuming as I'm running the loop two times, 1st to search the node and note down the position and 2nd to delete it.
struct node{
char word[20];
char meaning[5][100];
struct node *next;
};
void del(struct node *head, char *word)
{
int found = 0, position = 0, i;
struct node *temp = head;
while(temp != NULL)
{
if(strcmp(temp->word, word) == 0)
{
found = 1;
break;
}
temp = temp->next;
position++;
}
if(found == 1)
{
temp = head;
if(position == 0)
{
head = temp->next;
free(temp);
}
for(i = 0; i < position-1; i++)
temp = temp->next;
struct node *temp2 = temp->next;
temp->next = temp2->next;
free(temp2);
printf("Word deleted..\n");
}
else printf("Word not found!\n");
}
is there any alternate way to optimize the program?

You just have to merge the two cycles together like this, here's a code example.
struct node{
char word[20];
char meaning[5][100];
struct node *next;
};
struct node *del(struct node *head, char *word)
{int found = 0, position = 0, i;
struct node *temp = head;
struct node *prev = NULL;
/*You should avoid breaks because they decrease legibility*/
while(temp != NULL)
{
if(strcmp(temp->word, word) == 0)
{
if(prev == NULL){ /*If the node is the head*/
head = head->next;
free(temp);
return head;
}else{
prev->next = temp->next;
free(temp);
return head;
}
}
prev = temp;
temp = temp->next;
}
}

Related

Why am I getting access denied error Reverse Linked List in C

Always get the error code. I'm trying to reverse transverse the list and print.
Is there something I'm missing in the creation of the list?
I can print the list normal but just not reversed
Any help would be appreciated
struct stNode {
char *pName;
double avg;
struct stNode *next;
struct stNode *prev;
}; //stNode
typedef struct stNode Node;
void createList(Node **head, Node **tail) {
Node* tmp;
Node* x;
for(int i = 0;i < INPUTSIZE; i++){
//stores values in nodes
tmp = malloc(sizeof(Node));
tmp->avg = f1input_avg[i];
tmp->pName = f1input_name[i];
tmp->next = NULL;
//If list is empty
if( *head == NULL){
*head = tmp;
}
//Creates subsequent nodes
else{
x = *head;
while(x->next != NULL){
x = x->next;
}
x->next = tmp;
}
}
} // createList
void RevprintList(Node *head){
Node *cur = NULL;
printf("=======Reversed List =======\n");
cur = head;
while (cur->next != NULL) {
cur = cur->next;
}
while (cur != head){
printf("%-15s %5.2lf\n", cur->pName, cur->avg);
cur = cur->prev;
}
}
int main() {
Node *head = NULL;
Node *tail = NULL;
createList(&head, &tail);
printList(head);
RevprintList(head);
freeList(&head, &tail);
}
Process returned -1073741819 (0xC0000005)

How to delete node from doubly linked list in c

I am working on doubly linked list in c, I have a doubly linked tepm2 with 20 nodes and I want to delete the node whose word user insert.
struct node {
struct node *prev;
char word[100];
int repeatTime;
struct node *next;
} *h, *temp, *temp1, *temp2;
Each node has unique word.
printf("\n Enter word to delete : ");
scanf("%s", &word);
Delete(word);
int delete(char data[200]) { //unable to delete
if (h == NULL)
return;
temp2 = next = previous = h;
while (temp2->next != NULL) {
if ((strcmp(temp2->word, data) == 0)) {
if (temp2->prev == NULL) {
h = temp2->next;
free(temp2);
return;
} else if (temp2->prev == NULL) {
previous->next = temp2;
free(temp2);
previous->next = NULL;
return;
} else {
previous->next = temp2->next;
next->prev = temp2->next;
}
}
temp2 = temp->next;
}
}
I am been unable to delete the specific node that word user enter
Try this:
int delete(const char *data)
{
struct node *temp = h;
if (h == NULL) return;
while (temp->next != NULL)
{
if (strcmp(temp->word, data) == 0)
{
if (temp->prev != NULL)
{
temp->prev->next = temp->next;
}
if (temp->next != NULL)
{
temp->next->prev = temp->prev;
}
if (h == temp)
{
h = temp->next;
}
free(temp);
return;
}
temp = temp->next;
}
}
First of all I don't think this is right temp2 = next = previous = h;
Now all you have to do is find the node that you want to delete by traversing and than link it's prev node to it's next node i.e. (temp2->prev)->next = next and (temp2->next)->prev = prev and free it.
Now the real issue lies with
1. The first node that has other nodes after it
2. last node that has other nodes preceding it
3. only node
You can simplify all three by converting them into the former problem i.e. node in the middle problem which we've just solved.
For simplifying you can just make the head and tail both NULL.

sorting a singly linked list with quicksort after user input and then inserting a new node and resorting list

I have my code for the most part but having a rough go of it trying to get my quick sort function to work and sort through the actual link list created. Don't know if I am calling the function improperly or if I have the struct correct.
The program will compile and run up until it gets to the calling function for the quicksort. Then it just freezes and does nothing. Any help would be great. Thank you a head of time.
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
struct node *link_list;
};
struct node *insertion(struct node *pointer, int i){
struct node *temp_val;
if(pointer == NULL){
pointer = (struct node *)malloc(sizeof(struct node));
if(pointer == NULL){
printf("Error Exiting\n");
exit(0);
}
pointer->data = i;
pointer->link_list = pointer;
}else{
temp_val = pointer;
while(temp_val->link_list != pointer){
temp_val = temp_val->link_list;
}
temp_val->link_list = (struct node *)malloc(sizeof(struct node));
if(temp_val->link_list == NULL){
printf("Error Exiting\n");
exit(0);
}
temp_val = temp_val->link_list;
temp_val->data = i;
temp_val->link_list = pointer;
}
return(pointer);
};
struct node *findPivot(struct node *head, struct node *term, struct node **newHead, struct node **newTerm){
struct node *pivot = term;
struct node *previous = NULL, *current = head, *tail = pivot;
//finding the pivot and dividing the list while also updating the head and term
// with newHead and newTerm
while(current != pivot){
if(current->data < pivot->data){
//assigning the newHead to the first value less then the pivot
if((*newHead) == NULL){
(*newHead) = current;
}
previous = current;
current = current->link_list;
}else{
// if the current node has a higher value then the pivot
// assinging it to newTerm
if(previous){
previous->link_list = current->link_list;
}
struct node *temp = current->link_list;
current->link_list = NULL;
tail->link_list = current;
tail = current;
current = temp;
}
}
//Checks the case if the pivot is the smallest value and moves to head
if((*newHead)== NULL){
(*newHead) = pivot;
}
(*newTerm) = tail; // makes sure the last element is newEnd
return pivot;
}
//finds the last node in the list and returns it
struct node *getTail(struct node *current){
while(current != NULL && current->link_list != NULL){
current = current->link_list;
}
return current;
}
// the actual recursive quicksort algorithm
struct node *quickSort(struct node *head, struct node *term){
if(!head || head == term) //base case for the recursion
return head;
struct node *newHead = NULL, *newTerm = NULL;
// the recursive case
struct node *pivot = findPivot(head, term, &newHead, &newTerm);
//no need for recursion if pivot is smallest value
if(newHead != pivot){
struct node *temp = newHead;
while(temp->link_list != pivot){
temp = temp->link_list;
}
temp->link_list = NULL;
newHead = quickSort(newHead, temp);
temp = getTail(newHead);
temp->link_list = pivot;
}
pivot->link_list = quickSort(pivot->link_list, newTerm);
return newHead;
}
void quickSortFunction(struct node **pointer){
*pointer = quickSort(*pointer, getTail(*pointer));
return;
}
void printList_Unsorted(struct node *pointer){
struct node *temp;
temp = pointer;
printf("\nThe Data values in the list are:\n");
if(pointer != NULL){
do{
printf("%d\t", temp->data);
temp = temp->link_list;
}while(temp != pointer);
}else{
printf("the list is empty\n");
}
}
void printList_Sorted(struct node *node){
while(node!= NULL){
printf("%d ", node->data);
node = node->link_list;
}
printf("\n");
}
int main(int argc, char *argv[]) {
int num_nodes, node_val;
struct node *list = NULL;
printf("Enter the number of nodes to be created: ");
scanf("%d", &num_nodes);
while(num_nodes --> 0){
printf("\n\nEnter the data values to be placed in a node: ");
scanf("%d", &node_val);
list = insertion(list, node_val);
}
printf("\n\nThe Created list is as follow:\n");
printList_Unsorted(list);
printf("\n");
quickSortFunction(&list);
printList_Sorted(list);
//getchar();
//getchar();
return 0;
}
Please look at this working example.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link_list;
};
void insertion(struct node **pointer, int i) {
struct node *temp_val = malloc(sizeof *temp_val);
temp_val->data = i;
temp_val->link_list = (*pointer);
(*pointer) = temp_val;
}
/* A utility function to print linked list */
void printList(struct node *node) {
while (node != NULL) {
printf("%d ", node->data);
node = node->link_list;
}
printf("\n");
}
// Returns the last node of the list
struct node *getTail(struct node *current) {
while (current != NULL && current->link_list != NULL)
current = current->link_list;
return current;
}
struct node *findPivot(struct node *head, struct node *term,
struct node **newHead, struct node **newTerm) {
struct node *pivot = term;
struct node *previous = NULL, *current = head, *tail = pivot;
while (current != pivot) {
if (current->data < pivot->data) {
if ((*newHead) == NULL)
(*newHead) = current;
previous = current;
current = current->link_list;
}
else
{
if (previous)
previous->link_list = current->link_list;
struct node *tmp = current->link_list;
current->link_list = NULL;
tail->link_list = current;
tail = current;
current = tmp;
}
}
// If the pivot data is the smallest element in the current list,
// pivot becomes the head
if ((*newHead) == NULL)
(*newHead) = pivot;
// Update newTerm to the current last node
(*newTerm) = tail;
// Return the pivot node
return pivot;
}
// the actual recursive quicksort algorithe
struct node *quickSort(struct node *head, struct node *end) {
// base case
if (!head || head == end)
return head;
struct node *newHead = NULL, *newEnd = NULL;
struct node *pivot = findPivot(head, end, &newHead, &newEnd);
if (newHead != pivot) {
struct node *tmp = newHead;
while (tmp->link_list != pivot)
tmp = tmp->link_list;
tmp->link_list = NULL;
newHead = quickSort(newHead, tmp);
tmp = getTail(newHead);
tmp->link_list = pivot;
}
pivot->link_list = quickSort(pivot->link_list, newEnd);
return newHead;
}
void quickSortFunction(struct node **headRef) {
(*headRef) = quickSort(*headRef, getTail(*headRef));
return;
}
int main() {
struct node *list = NULL;
int num_nodes, node_val;
printf("Enter the number of nodes to be created: ");
scanf("%d", &num_nodes);
while(num_nodes --> 0){
printf("\n\nEnter the data values to be placed in a node: ");
scanf("%d", &node_val);
insertion(&list, node_val);
}
printf("\n\nThe Created list is as follows:\n");
printList(list);
printf("\n");
quickSortFunction(&list);
printList(list);
return 0;
}
Test
/home/dac/.CLion2016.2/system/cmake/generated/gnu-fadf49ce/fadf49ce/Debug/gnu
Enter the number of nodes to be created: 3
Enter the data values to be placed in a node: 2
Enter the data values to be placed in a node: 4
Enter the data values to be placed in a node: 3
The Created list is as follows:
3 4 2
2 3 4
Process finished with exit code 0
The problem with your code was that it entered an infinite loop because the parameter was not a pointer to the node, but a pointer to the struct. You also don't need to return the list because you are passing it by reference.

LinkedList functions crash in c

I implemented a linked list in c. when i test it, whenever i reach display function or insert at the end the program crashes. These are the functions:
struct Node
{
char data;
struct Node *next;
};
struct LinkedList
{
struct Node *head;
};
void insertAtBeginning(struct LinkedList *LL, char ele)
{
struct Node *new = (struct Node*)malloc(sizeof(struct Node));
new->data = ele;
new->next = NULL;
if(new->data == '\n')return;
if(LL->head==NULL)LL->head = new;
else
{
new->next=LL->head;
LL->head=new;
}
}
void insertAtTheEnd(struct LinkedList *LL, char ele)
{
struct Node *new = (struct Node*) malloc(sizeof(struct Node));
new->data = ele;
new->next = NULL;
if(LL->head==NULL){LL->head=new;return;}
struct Node *current = LL->head;
while(current->next != NULL) {current = current->next;}
current->next = new;
}
void deleteNode(struct LinkedList* LL, char ele)
{
struct Node *current = LL->head;
struct Node *temp = LL->head;
while(current->next->data!=ele && current!=NULL)current=current->next;
temp=current->next;
current->next=current->next->next;
free(temp);
}
void deleteFirstNode(struct LinkedList* LL)
{
struct Node *temp;
if(LL->head != NULL)
{
temp = LL->head;
LL->head = LL->head->next;
free(temp);
}
}
void displayLinkedList(struct LinkedList LL)
{
struct Node *current = LL.head;
printf("List: ");
while(current != NULL)
{
printf("%c",current->data);
current = current->next;
}
printf("\n");
}
This is the main:
main()
{
struct LinkedList LL;
char c = '0';
//Inserting at beginning
printf("Type a string. Press Enter to end: ");
while(c != '\n')
{
scanf("%c",&c);
insertAtBeginning(&LL, c);
}
printf("List: ");
displayLinkedList(LL);
printf("\n");
//Inserting at end
c='0';
printf("Type a string. Press Enter to end: ");
while(c != '\n')
{
scanf("%c",&c);
insertAtTheEnd(&LL, c);
}
printf("List: ");
displayLinkedList(LL);
printf("\n");
//Remove
printf("Enter a char to remove: ");
scanf("%c",&c);
deleteNode(&LL, c);
printf("\n");
printf("List: ");
displayLinkedList(LL);
printf("\n");
deleteFirstNode(&LL);
printf("List: ");
displayLinkedList(LL);
}
of course This is done after inserting the necessary libraries.
you have to set NULL to next when you create element. if you do not do it, your while loop behaviour will be buggy
void insertAtTheEnd(struct LinkedList *LL, char ele)
{
struct Node *new = (struct Node*) malloc(sizeof(struct Node));
new->next = NULL;
new->data = ele;
if(LL->head == NULL) LL->head = new;
else
{
struct Node *current = LL->head;
while(current->next != NULL) {current = current->next;}
current->next = new;
}
}
, and do same for other functions.
also you have to set NULL to your LinkedList.head. so, set NULL when you define LinkedList
struct LinkedList LL;
LL.head = NULL;
i asume the line if(current = LL->head) is wrong
bacause temp = current->next would crash if the result is NULL
otherwise the code after the if statement doesnt makes sense
There are some instances where you will try to insert at the end. When you have something of the form node_new->next->prev = node, you must check to make sure that node_new->next is not NULL, because NULL does not have any type and thus does not have a prev field.
You may also consider making all of your functions return int, so that you can know if and what goes wrong.

Deleting front node from a Singly Linked List in C

I am trying to delete from a Singly Linked List, however, when I try to delete from the first element, it prints garbage. I think the problem comes from the delete_node function, however, I tried everything and I cannot figure it out.
#include <stdio.h>//prinf
#include <stdlib.h>//alloc mallco callo
typedef struct node node;
struct node{
int number;
node *next;
};
node *new_node(int num){
node *n= (node*) malloc(sizeof(node));
n->number=num;
n->next=NULL;
return n;
}
void node_free_all(node *n){
if(n != NULL){
node_free_all(n->next);
free(n);
}
}
void print_nodes(node *n){
if(n != NULL){
print_nodes(n->next);
printf("Number is: %d\n",n->number);
}
}
void delete_node(node *n, int num){
node *rmNode= (node*)malloc(sizeof(node));
//delete first
if( n!= NULL && n->number==num){
rmNode = n;
n=n->next;
free(rmNode);
}
//all but first
while(n != NULL){
if(n->next != NULL && n->next->number == num){
rmNode= n->next;
n->next = rmNode->next;
free(rmNode);
break;
}
n=n->next;
}
}
int main(){
int i;
node *head= (node*) malloc(sizeof(node));
node *curr;
head=NULL;
for(i=1;i<=10;i++) {
curr = new_node(i);
curr->next =head;
head=curr;
}
printf("Everything:\n");
print_nodes(head);
printf("Deleting 1:\n");
delete_node(head,1);
print_nodes(head);
printf("Deleting 5:\n");
delete_node(head,5);
print_nodes(head);
printf("Deleting 2:\n");
delete_node(head,2);
print_nodes(head);
printf("Deleting 3:\n");
delete_node(head,3);
print_nodes(head);
printf("Deleting 10:\n");
delete_node(head,10);
print_nodes(head);
printf("Deleting 9:\n");
delete_node(head,9);
print_nodes(head);
node_free_all(head);
// node_free_all(list);
return 0;
}
What am I doing wrong?
You don't need to allocate memory to rmNode. Plus you need to pass the reference of head pointer to the function delete_node because every time you are updating the list and if you have to delete first element of list, then in this case head pointer also got updated.
struct node
{
int number;
node *next;
};
void delete_node(struct node** head_ref, int num)
{
struct node* temp;
struct node* current = (*head_ref);
//delete first
if( current != NULL && current->number == num)
{
temp = current;
current = current->next;
free(temp);
(*head_ref) = current;
}
else
{
//all but first
while(current != NULL)
{
if(current->next != NULL && current->next->number == num)
{
temp = current->next;
current->next = temp->next;
free(temp);
break;
}
current = current->next;
}
}
}
here's a version that removes all items that matches num, and always update the head item.
void delete_node(node** head_ref, int num)
{
node* temp;
node* last = 0;
node* current = *head_ref;
while(current)
{
if( current->number == num )
{
temp = current;
if( current == *head_ref )
current = (*head_ref) = current->next;
else
current = last->next = current->next;
free(temp);
} else {
last = current;
current = current->next;
}
}
}
You have to call it like delete_node(&head,1);
because it needs an address to the head item to be able to change it

Resources