#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
struct node *prev;
}*head=NULL;
int length(struct node *p)
{
int len;
while(p!=NULL)
{
len++;
p = p->next;
}
return len;
}
void display(struct node *p)
{
if(p == NULL)
{
printf("Linked List is empty\n");
}
else
{
printf("Linked List: ");
while(p!=NULL)
{
printf("%d ", p->data);
p = p->next;
}
}
}
void insert(struct node *p, int index, int x)
{
struct node *t;
if(index == 0)
{
t = (struct node *)malloc(sizeof(struct node));
t->data = x;
t->next = head;
t->prev = NULL;
if(head != NULL)
{
head->prev = t;
}
head = t;
}
else
{
t = (struct node *)malloc(sizeof(struct node));
t->data = x;
for(int i=0; i<index-1; i++)
{
p = p->next;
}
t->prev = p;
t->next = p->next;
if(p->next != NULL)
{
p->next->prev = t;
}
p->next = t;
}
}
int checkprime(int n)
{
int prime = 1;
for(int i=2; i<n; i++)
{
if(n % 2 == 0)
{
prime = 0;
break;
}
}
if(prime == 0)
{
return 0; //It is not a prime number.
}
else
{
return 1; //It is a prime number.
}
}
void delete_prime_number(struct node *p)
{
struct node *q;
while(p != NULL)
{
q = p;
p = p->next;
if((checkprime(q->data)) == 1)
{
free(q);
}
}
}
int main()
{
insert(head, 0, 2);
insert(head, 1, 3);
insert(head, 2, 4);
insert(head, 3, 7);
insert(head, 4, 8);
insert(head, 5, 12);
insert(head, 6, 15);
insert(head, 7, 23);
display(head);
delete_prime_number(head);
display(head);
return 0;
}
This is the code I have tried for this. The problem is in the delete_prime_function. When I run it, it prints random values unlimited times.
I created a checkprime function which will return 1 if the number is prime and return 0 if the number is not prime.
Then in the delete_prime function, each time it would check the condition if((checkprime)==1), and if its true it would delete that node, and the process would go on until pointer "p" reaches NULL.
I'm not getting where I am doing it wrong.
EDIT:
Thank you, I implemented what #pmg and #VladfromMoscow pointed out. Here is the working code.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
struct node *prev;
};
int length(struct node *p)
{
int len = 0;
while (p != NULL)
{
len++;
p = p->next;
}
return len;
}
void display(struct node *p)
{
if (p == NULL)
{
printf("Linked List is empty\n");
}
else
{
printf("Linked List: ");
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
}
}
void insert(struct node **p, int index, int x)
{
struct node *t;
if (index == 0)
{
t = (struct node *)malloc(sizeof(struct node));
t->data = x;
t->next = *p;
t->prev = NULL;
if ((*p) != NULL)
{
(*p)->prev = t;
}
(*p) = t;
}
else
{
t = (struct node *)malloc(sizeof(struct node));
t->data = x;
for (int i = 0; i < index - 1; i++)
{
if((*p) == NULL)
{
printf("Linked List is empty!\n");
}
else
{
p = &(*p)->next;
}
}
t->prev = (*p);
t->next = (*p)->next;
if ((*p)->next != NULL)
{
(*p)->next->prev = t;
}
(*p)->next = t;
}
}
int checkprime(int n)
{
int prime = 1;
if(n == 0 || n == 1)
{
return 0;
}
else
{
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
prime = 0;
break;
}
}
if (prime == 0)
{
return 0; //It is not a prime number.
}
else
{
return 1; //It is a prime number.
}
}
}
void delete_prime_number(struct node **p)
{
while (*p != NULL)
{
if (checkprime((*p)->data) == 1)
{
struct node *q = *p;
if ((*p)->next != NULL)
{
(*p)->next->prev = (*p)->prev;
}
*p = (*p)->next;
free(q);
}
else
{
p = &(*p)->next;
}
}
}
int main()
{
struct node *head = NULL;
insert(&head, 0, 2);
insert(&head, 1, 3);
insert(&head, 2, 4);
insert(&head, 3, 7);
insert(&head, 4, 8);
insert(&head, 5, 12);
insert(&head, 6, 15);
insert(&head, 7, 23);
display(head);
delete_prime_number(&head);
printf("\n");
display(head);
return 0;
}
Thanks again :)
Imagine this 3 nodes list:
NULL==p /<==p /<==p
NODE NODE NODE
n==>/ n==>/ n==NULL
When you remove the 2nd node in this list you want to get
NULL==p /<==========p // changed prev link in 3rd node
NODE ---- NODE // deleted 2nd node
n==========>/ n==NULL // changed next link in 1st node
But your code is getting this
NULL==p ---- /<==p // prev links to deleted node
NODE ---- NODE
n==>/ ---- n==NULL // next links to deleted node
Beware the special cases of the first and last nodes in the list.
Your implementation of the list is incorrect and many functions can invoke undefined behavior.
For starters the functions shall not rely on the global variable head. In this case a program for example can not use two lists simultaneously.
The function length invokes undefined behavior because the local variable len is not initialized.
int length(struct node *p)
{
int len;
while(p!=NULL)
{
len++;
p = p->next;
}
return len;
}
You need to write
int len = 0;
In the function insert in this code snippet
for(int i=0; i<index-1; i++)
{
p = p->next;
}
t->prev = p;
t->next = p->next;
if(p->next != NULL)
{
p->next->prev = t;
}
p->next = t;
you do not check whether p is equal to NULL. For example if the list is empty that is head is a null pointer and the user specified index equal to 1 then p also will be a null pointer. So using it in expressions like for example this p->next invokes undefined behavior.
The function checkprime is also incorrect. It shows that numbers 0, 1 and all odd numbers are prime numbers due to the if statement
if(n % 2 == 0)
{
prime = 0;
break;
}
that will not get the control for such numbers.
So at first you have to write the list (declaring head as a local variable) and all the mentioned functions correctly before writing the function delete_prime_number which naturally also incorrect because at least it does not change the pointer head when the pointed node contains a prime number.
As for the function delete_prime_number itself then it can be defined the following wat
void delete_prime_number( struct node **head )
{
while ( *head != NULL )
{
if ( checkprime( ( *head )->data ) )
{
struct node *tmp = *head;
if ( ( *head )->next != NULL )
{
( *head )->next->prev = ( *head )->prev;
}
*head = ( *head )->next;
free( tmp );
}
else
{
head = &( *head )->next;
}
}
}
and can be called like
delete_prime_number( &head );
Related
I am new to C programming and When I asked user to input a number for some reason my whole program gives this error
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555753 in addData (word=0x7fffffffeb70 "", mode=2) at main.c:202
202 if (temp->next == NULL) {
(gdb)
HERE IS MY CODE
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define MEMORY 6
#define MAX_word_LENGTH 11
int numberOfwords;
char words[MEMORY][MAX_word_LENGTH];
struct Node{
int data;
char *word;
struct Node *next, *prev;
};
struct Node *head, *tail;
struct Node* DlListDeleteLastNode(struct Node *head);
void addData(char *word, int mode);
void DisplayForward();
struct Node* deletePos(struct Node *head, int pos);
int getPostion(char *targetWord);
bool search(char *targetWord);
//struct Node* deletePos(struct Node *head, int pos);
int countWord(char *wording);
void insert_specified(char *wording, int pos);
int countNodes();
//void init(){
// head = NULL;
// tail = NULL;
//}
int main()
{
char name[100];
//char searchName[] = "barr";
printf("Enter number of words to be stored in the word stream: ");
int input;
scanf("%d", &input);
int i;
int count = 0;
for (i=0; i<input;i++){
count++;
printf("\nEnter name %d : ",count);
scanf ("%[^\n]%*c", name);
//scanf("%s[^\n]",words[i]);
addData(name, 2);
}
//for (int i = 0; i <4; i++) {
// strcpy(words[i],
//}
//insert_specified(searchName, 0);
//printf("%d\n", numberOfwords);
//DlListDeleteLastNode();
DisplayForward();
//int num = countNodes();
//printf("count %d", num);
//deletePos(head, 3);
//bool x = search(searchName);
//printf("%d\n", x);
//printf("%d\n", numberOfwords);
//DisplayForward();
//fflush(stdin);
printf("\nEntered names are:\n");
for(i=0;i<6;i++)
puts(words[i]);
}
int isEmpty(struct Node *h){
if(h==NULL)
return 1;
else
return 0;
}
void addData(char *word, int mode){
if (mode == 1) {
for (int i=0; i<5; i++) {
if (strcmp(words[i],word) == 0) {
//printf("found\n");
//printf("FOUND%s\n", word);
int x = getPostion(word);
//printf("index found %d/n", x);
//deletePos(head, x);
struct Node* temp = head;
struct Node* temp2 = NULL;
while (x > 1) {
temp = temp->next;
x--;
}
if (temp->next == NULL) {
head = DlListDeleteLastNode(head);
}
else {
temp2 = temp->prev;
temp2->next = temp->next;
temp->next->prev = temp2;
free(temp);
temp = NULL;
}
break;
}
//x index = getPostion()
}
if (numberOfwords >= 5) {
DlListDeleteLastNode(head);
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
numberOfwords++;
}
else {
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
numberOfwords++;
strcpy(words[numberOfwords], word);
}
}
else {
int flag = 0;
//int numWords = countNodes();
for (int i=0; i<8; i++) {
if (strcmp(words[i],word) == 0) {
//printf("found\n");
//printf("FOUND%s\n", word);
int x = getPostion(word);
//printf("index found %d/n", x);
//deletePos(head, x); //
struct Node* temp = head;
struct Node* temp2 = NULL;
while (x > 1) {
temp = temp->next;
x--;
}
if (temp->next == NULL) {
head = DlListDeleteLastNode(head);
}
else {
temp2 = temp->prev;
temp2->next = temp->next;
temp->next->prev = temp2;
free(temp);
temp = NULL;
}
flag = 1;
//DisplayForward();
//numberOfwords--;
break;
}
//x index = getPostion()
}
printf("\nflag num-> %d\n", flag);
//numberOfwords++;
int numWords = countNodes();
if (numWords >= 5 && flag==0) {
//printf("activated");
int max = 0;
char maxWord[50];
for (int i = 0; i < 8; i++) {
int num = countWord(words[i]);
if (num > max) {
max = num;
//printf("%d", max);
strcpy(maxWord, words[i]);
//printf("word %s\n", maxWord);
}
}
printf("most occured word: %s\n", maxWord);
int mostOccuredWordIndex = getPostion(maxWord);
printf("index: %d\n", mostOccuredWordIndex);
mostOccuredWordIndex--;
insert_specified(word, mostOccuredWordIndex);
DlListDeleteLastNode(head);
}
else if (numWords >= 5) {
//DlListDeleteLastNode(head);
//struct Node *ptr;
//ptr= malloc(sizeof *ptr);
//ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
//Get most occured word in words array
//find the position of the most occured word
//int mostOccuredWordIndex = getPostion(maxWord);
//remove last element and insert new word into that position
//if position is in the last index then remove word and replace with the word
//if (mostOccuredWordIndex == 5) {
// printf("occurred");
//}
//
DlListDeleteLastNode(head);
numberOfwords = numberOfwords + 1;
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
}
else {
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
numberOfwords = numberOfwords + 1;
strcpy(words[numberOfwords], word);
}
DisplayForward();
numWords = countNodes();
printf("\nnumber of words%d \n", numWords);
}
}
struct Node* DlListDeleteLastNode(struct Node *head) {
struct Node *temp = head;
struct Node* temp2;
while (temp->next != NULL) {
temp = temp->next;
}
temp2 = temp->prev;
temp2->next = NULL;
free(temp);
numberOfwords--;
return head;
}
void DisplayForward() {
//Node current will point to head
struct Node *current = head;
if(head == NULL) {
printf("List is empty\n");
return;
}
printf("[");
int count = numberOfwords;
// while current->next != Null
while(current!=NULL) {
//Prints each node by incrementing pointer.
printf("%s, ", current->word);
current = current->next;
count--;
}
//current = current->next;
//printf("%s]\n", current->word);
//printf("%d", numberOfwords);
}
bool search(char *targetWord) {
int pos = 0;
if(head==NULL) {
printf("Linked List not initialized");
return;
}
struct Node *current = head;
//current = head;
while(current!=NULL) {
pos++;
if(strcmp(current->word, targetWord) == 0) {
printf("%s found at position %d\n", targetWord, pos);
return true;
}
if(current->next != NULL)
current = current->next;
else
break;
}
return false;
//printf("%s does not exist in the list\n", targetWord);
}
int getPostion(char *targetWord) {
int pos = 0;
if(head==NULL) {
printf("Linked List not initialized");
return -1;
}
struct Node *current = head;
//current = head;
while(current!=NULL) {
pos++;
if(strcmp(current->word, targetWord) == 0) {
//printf("%s found at position %d\n", targetWord, pos);
return pos;
}
if(current->next != NULL)
current = current->next;
else
break;
}
return -1;
//printf("%s does not exist in the list\n", targetWord);
}
int countWord(char *wording) {
int count = 0;
for(int i=0;i<6;i++) {
if (strcmp(words[i], wording)==0) {
//printf("found word");
count++;
}
}
return count;
}
void insert_specified(char * wording, int pos)
{
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
struct Node *temp;
int i;
if(ptr == NULL)
{
printf("\n OVERFLOW");
}
else
{
//printf("\nEnter the location\n");
//scanf("%d",&loc);
temp=head;
for(i=0;i<pos;i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("\ncan't insert\n");
return;
}
}
strcpy(ptr->word, wording);
ptr->next = temp->next;
ptr -> prev = temp;
temp->next = ptr;
temp->next->prev=ptr;
printf("Node Inserted\n");
}
}
int countNodes() {
int counter = 0;
//Node current will point to head
struct Node *current = head;
while(current != NULL) {
//Increment the counter by 1 for each node
counter++;
current = current->next;
}
return counter;
}
I tried to ask the user for a number of words it wants to input for my program to store the items in a doubly linked list but instead gives a segmentation fault error
struct Node *head is a global variable which is zero initialized. In addData() you set struct Node* temp = head; and then you deference temp like your stack trace shows which will segfault.
Anyways, before you even get there the 2nd scanf() fails as it the input buffer contains the \n from reading the previous number. The syntax of the format string also looks wrong to me. In any case as you don't check the return value of you are operating on uninitialized data. Here is the minimal fix:
if(scanf(" %99[^\n]*", name) != 1) {
printf("scanf failed\n");
return 1;
}
I also replaced the hard-coded < 8 with < MEMORY to avoid a buffer overflow. Here is an example run:
Enter number of words to be stored in the word stream: 2
Enter name 1 : test
flag num-> 0
[test,
number of words1
Enter name 2 : test2
flag num-> 0
[test2, test,
number of words2
[test2, test,
Entered names are:
test
test2
I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
int x;
struct Node *next;
} Node;
void deallocate(Node **root)
{
Node *curr = *root;
while (curr != NULL)
{
Node *aux = curr;
curr = curr->next;
free(aux);
}
*root = NULL;
}
void insert_end(Node **root, int value)
{
Node *new_node = malloc(sizeof(Node));
if (new_node == NULL)
{
exit(1);
}
new_node->next = NULL;
new_node->x = value;
if (*root == NULL)
{
*root = new_node;
return;
}
Node *curr = *root;
while (curr->next != NULL)
{
curr = curr->next;
}
curr->next = new_node;
}
void deserialize(Node **root)
{
FILE *file = fopen("duom.txt", "r");
if (file == NULL)
{
exit(2);
}
int val;
while (fscanf(file, "%d, ", &val) > 0)
{
insert_end(root, val);
}
fclose(file);
}
int largestElement(struct Node *root)
{
int max = INT_MIN;
while (root != NULL)
{
if (max < root->x)
max = root->x;
root = root->next;
}
return max;
}
void deleteN(Node **head, int position)
{
Node *temp;
Node *prev;
temp = *head;
prev = *head;
for (int i = 0; i < position; i++)
{
if (i == 0 && position == 1)
{
*head = (*head)->next;
free(temp);
}
else
{
if (i == position - 1 && temp)
{
prev->next = temp->next;
free(temp);
}
else
{
prev = temp;
// Position was greater than
// number of nodes in the list
if (prev == NULL)
break;
temp = temp->next;
}
}
}
}
int main()
{
Node *root = NULL;
printf("MENU:\n");
printf("if you press 0 the list will be created \n");
printf("if you press 1 the list will be printed on a screen\n");
printf("if you press 2 it deletes the biggest element\n");
printf("if you press 3 the program ends\n\n");
int meniu;
printf("press:\n");
scanf("%d", &meniu);
while (meniu != 3)
{
if (meniu == 0)
{
deserialize(&root);
printf("sarasas sukurtas.\n");
}
if (meniu == 1)
{
for (Node *curr = root; curr != NULL; curr = curr->next)
printf("%d\n", curr->x);
}
if (meniu == 2)
{
int max_element = largestElement(root);
printf("%d max\n", max_element);
deleteN(&root, max_element);
}
printf("press:\n");
scanf("%d", &meniu);
}
deallocate(&root);
return 0;
}
When I compile and run the delete function it only deletes the biggest number first time and if I call it second time it deletes the last number of the list. Can someone help me fix that?
I edited it so all of the code can be seen because it was hard to understand it like I had it before
Your largestElement returns the largest data value in the list.
However, here:
int max_element = largestElement(root);
printf("%d max\n",max_element);
deleteN(&root, max_element);
you use the return value as if it is the position of the node with the largest element.
Instead of largestElement you need a function that returns the position of the element with the largest data value.
It would look something like:
int positionOfLargestElement(struct Node* root)
{
int pos = 0;
int maxpos = 0;
int max = INT_MIN;
while (root != NULL) {
++pos;
if (max < root->x)
{
max = root->x;
maxpos = pos;
}
root = root->next;
}
return maxpos;
}
note: The exact code depends a bit on whether the first node is considered to be position 0 or position 1 but the principle is the same.
I got problem with Singly Linked List problem.
When i inserted something in front of head. head is always have 0 of data.
I think init_list() function is something wrong. I think head of 0 is from randomly initialized data.
anything is fine without head 0 problem.
I'm sure that initializing method is wrong. But I don't know how to solve it..
Here is my I/0 and Desired Output
Input
2
insert 0 1
size
Output I got
1->0->NULL
2
1->0->NULL
Desired Output
1->NULL
1
1->NULL
Here is My Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int Element;
typedef struct LinkedNode {
Element data;
struct LinkedNode* link;
} Node;
Node* head;
void init_list() {
head = (Node*)malloc(sizeof(Node));
head->link = NULL;
}
int is_empty() {
if (head == NULL) return 1;
else return 0;
}
Node* get_entry(int pos)
{
Node* p = head;
int i;
for (i = 0; i < pos; i++, p=p->link){
if (p == NULL) return NULL;
}
return p;
}
int size()
{
Node* p;
int count = 0;
for (p = head; p != NULL; p = p->link)
count++;
return count;
}
void replace(int pos, Element val)
{
Node* node = get_entry(pos);
if (node != NULL)
node->data = val; // replace
}
Node* search_list(Element val)
{
Node* p;
for (p = head; p != NULL; p = p->link)
if (p->data == val) return p;
return NULL;
}
void insert_next(Node * before, Node * node)
{
if (node != NULL) {
node->link = before->link;
before->link = node;
}
}
void insert(int pos, Element val)
{
Node* new_node, * prev;
new_node = (Node*)malloc(sizeof(Node));
new_node->data = val;
if (pos == 0) {
new_node->link = head;
head = new_node;
}
else {
prev = get_entry(pos-1);
if (prev != NULL)
insert_next(prev, new_node);
else free(new_node);
}
}
Node * remove_next(Node * prev)
{
Node* removed = prev->link;
if (removed != NULL) {
prev->link = removed->link;
}
return removed;
}
void delete(int pos)
{
Node* prev, * removed;
if (pos == 0 && is_empty() == 0) {
removed = get_entry(pos);
head = head->link;
free(removed);
}
else {
prev = get_entry(pos-1);
if (prev != NULL) {
remove_next(prev);
free(removed);
}
}
}
void clear_list()
{
while (is_empty() == 0)
delete(0);
}
void print_list()
{
Node* p;
for (p = head; p != NULL; p = p->link)
printf("%d->", p->data);
printf("NULL\n");
}
Node * concat_list(Node * new_node)
{
if(is_empty()) return new_node;
else if(new_node == NULL) return new_node;
else{
Node* p;
p = head;
while (p->link != NULL) {
p = p->link;
}
p->link = new_node;
return head;
}
}
int main(void)
{
Element num;
int pos;
int n, i, j, len;
char c[15];
Node* tmp_head= NULL;
Node* new_head= NULL;
init_list();
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%s", c);
if (strcmp(c, "insert") == 0) { scanf("%d %d\n",&pos, &num); insert(pos,num); print_list();}
else if (strcmp(c, "delete") == 0) { scanf("%d\n", &pos); delete(pos); print_list();}
else if (strcmp(c, "size") == 0) {printf("%d\n", size()); print_list();}
else if (strcmp(c, "empty") == 0) {printf("%d\n", is_empty()); print_list();}
else if (strcmp(c, "getEntry") == 0) { scanf("%d\n", &pos); printf("%d\n", get_entry(pos)->data); print_list();}
else if (strcmp(c, "search_list") == 0) { scanf("%d\n", &num); printf("%d\n", search_list(num)->data); print_list();}
else if (strcmp(c, "replace") == 0) { scanf("%d %d\n", &pos, &num); replace(pos,num); print_list();}
else if (strcmp(c, "concat_list") == 0) {
tmp_head = head;
init_list();
scanf("%d", &len);
for (j = 0; j < len; j++)
{
scanf("%d %d\n",&pos, &num); insert(pos,num);
}
printf("new_node: ");
print_list();
new_head = head;
head = tmp_head;
head = concat_list(new_head);
print_list();
}
else printf("error\n");
}
return 0;
}
The basic problem is that within init_list, the code only initializes link but not data. I'd suggest instead that you initialize head to NULL and simply use insert to create nodes.
#include <stdio.h>
#include <malloc.h>
struct el {
int info;
struct el* next;
};
struct el* create_el(struct el* Li)
{
int num;
printf("\n\nInsert number:\n\n");
scanf("%d", &num);
Li = (struct el*)malloc(sizeof(struct el));
if (Li != NULL) {
Li->info = num;
Li->next = NULL;
}
return (Li);
}
struct el* push(struct el* L, struct el* e)
{ //inserts the elements from the head of the list
if (L == NULL)
return (e);
else {
e->next = L;
L = e;
return (L);
}
}
void visualize(struct el* primo)
{
printf("\n\nList-->");
while (primo->next != NULL) {
printf("%d", primo->info);
printf("-->");
primo = primo->next;
}
if (primo->next == NULL)
printf("%d-->NULL", primo->info);
}
struct el* cancel(struct el** P, int val)
{ //delete element
struct el* prec = NULL;
struct el* curr = (*P);
if (P == NULL) //case empty list
return NULL;
else if (prec == NULL) {
if (curr->info == val) { //case 2 : if the element is the head
(*P)->next = curr->next;
free(curr);
curr = NULL;
}
}
else {
while ((curr != NULL) && (curr->info != val)) {
prec = curr;
curr = curr->next;
}
if (curr->next == NULL && curr->info == val) { // case 3: the elemnt is the last one
prec->next = NULL;
free(curr);
curr = NULL;
return (prec);
}
else {
if (curr->info == val) { //other cases
prec->next = curr->next;
free(curr);
curr = NULL;
return (prec);
}
}
}
}
int main()
{
struct el* head = NULL;
struct el* element;
struct el* list = NULL;
int i, n;
int elem;
printf("Insert the number of elements for the list:\n\n");
scanf("%d", &n);
for (i = 0; i <= n; i++) {
element = create_el(head);
if (element != NULL) {
list = push(list, element);
}
}
visualize(list);
printf("\n\nInsert the element that you want to cancel:");
elem = scanf("%d", &elem);
cancel(&list, elem);
visualize(list);
}
All I've wanted to do was delete an element from a listr, but after all the procediment the list is printed without any modification.
Can anyone see whats wrong in the function cancel(which is meant to delete an element by including any possible position of it)?
In your function cancel, P is definitely not NULL (assuming OS has assigned it an address initially).
prec is NULL the before execution enters if loop.
So, execution executes the line
if(curr->info==val)
Now, if the value, val, you have provided doesn't match curr->info then execution exits the function without deleting any node.
Here I have a header file to include functions:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node** top, node* newNode, node** last) {
node* current;
if (*top == NULL) {
*top = newNode;
} else if ((*top)->data >= newNode->data) {
newNode->next = *top;
newNode->next->prev = newNode;
*top = newNode;
if ((*top)->next == NULL) {
*last = *top;
}
} else {
current = *top;
while (current->next != NULL &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
if (current->next != NULL) {
newNode->next->prev = newNode;
}
current->next = newNode;
newNode->prev = current;
}
if ((*top)->next == NULL) {
*last = *top;
}
}
void insertionSort(node** top, node** last) {
node* sorted = NULL;
node* current = *top;
while (current != NULL) {
node* next = current->next;
current->prev = current->next = NULL;
sortedInsert(&sorted, current, last);
current = next;
}
*top = sorted;
}
node* deleteByPos(node* list, node** last, int position) {
int c = 0;
node* temp;
node* prev;
temp=list;
if (temp==NULL) {
printf("No nodes available to delete\n\n");
return list;
} else {
while(temp!=NULL && c != position) {
prev=temp;
temp=temp->next;
c++;
}
if (temp==NULL) {
printf("Reached end of list, position not available\n\n");
return list;
} else if (temp->next == NULL) {
prev->next=temp->next;
*last = prev;
free(temp);
return list;
} else {
prev->next=temp->next;
temp->next->prev = prev;
free(temp);
return list;
}
}
}
node* makeNode(int n) {
node* np = malloc(sizeof (node));
np->data = n;
np->prev = NULL;
np->next = NULL;
return np;
}
void printList(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->next;
}
}
void printListReverse(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->prev;
}
}
#endif /* driver_h */
and a main file:
#include "driver.h"
int main() {
int n;
node* np;
node* top;
node* last;
printf("Enter integers to add to list\n");
do {
if (scanf("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
if (top == NULL) {
top = np;
} else {
last->next = np;
np->prev = last;
}
last = np;
}
} while (n != 0);
printf("\n\n");
printf("You entered:\n");
printList(top);
printf("\n\n");
printf("In reverse:\n");
printListReverse(last);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
top = deleteByPos(top, &last, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(last);
insertionSort(&top, &last);
printf("From top after sort:\n");
printList(top);
printf("In reverse after Sort:\n");
printListReverse(last);
}
What this program does is take user input of integers, stores them in a doubly linked list, deletes a node at a user defined point and then performs an insertion sort. What I am trying to do is save a pointer to the last node in the sortedInsert function with the following code:
if ((*top)->next == NULL) {
*last = *top;
}
However, if you enter 6 5 3 1 9 8 4 2 7 4 2, then delete at position 2, when printing in reverse it prints out 6 5 4 4 2 2 1. For some reason it skips over 9 7 8. I cannot figure out why or how to fix this. How can I do this properly?
With lists, it helps to draw a diagram for all the cases. It's natural to use induction on lists to prove your code is correct.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> /* Asserting is useful when it come to lists especially. */
struct node {
struct node* next;
struct node* prev;
int data;
};
/* Saves you from dealing with 'top' and 'tail' every time. */
struct list {
struct node *head, *tail;
};
/* https://en.wikipedia.org/wiki/Insertion_sort */
void insertionSort(struct list* list) {
struct node* i = list->head, *j0, *j1;
while(i) {
j1 = i, j0 = j1->prev;
while(j0 && j0->data > j1->data) {
/* Swap. */
int temp = j0->data;
j0->data = j1->data;
j1->data = temp;
/* Decrement. */
j1 = j0;
j0 = j0->prev;
}
i = i->next;
}
}
/* Returns whether the position was deleted. */
int deleteByPos(struct list* list, int position) {
struct node* n;
assert(list);
/* Node n is the position's in the list. */
for(n = list->head; n && position; n = n->next, position--);
if (n==NULL) {
printf("No nodes available to delete\n\n");
return 0;
}
/* Fixme: If I'm not mistaken, there are 9 cases for you to be
mathematically certain this works, and I haven't tried them all.
Eg, 1 node, 2 nodes x2, 3 nodes x3, where the internal node is the 2nd of
the 3 nodes. */
if(n->prev == NULL) {
/* The first one. */
assert(list->head == n);
list->head = n->next;
if(n->next) n->next->prev = NULL;
} else {
/* Skip over. */
n->prev->next = n->next;
}
if(n->next == NULL) {
/* The last one. */
assert(list->tail == n);
list->tail = n->prev;
if(n->prev) n->prev->next = NULL;
} else {
/* Skip over. */
n->next->prev = n->prev;
}
n->prev = n->next = NULL; /* Helps in debugging. */
free(n);
return 1;
}
struct node* makeNode(struct list *list, int n) {
struct node* np = malloc(sizeof *np);
if(!np) return 0;
np->data = n;
np->prev = list->tail;
np->next = NULL;
/* Push it in the list. */
if(list->tail) {
assert(list->head != NULL && list->tail->next == NULL);
list->tail->next = np;
} else {
/* The first one. */
assert(list->head == NULL && list->tail == NULL);
list->head = np;
}
list->tail = np;
return np;
}
void printList(const struct list*const list) {
const struct node *n = list->head;
while (n) {
printf("%d\n", n->data);
n = n->next;
}
}
void printListReverse(const struct list*const list) {
const struct node *n = list->tail;
while (n) {
printf("%d\n", n->data);
n = n->prev;
}
}
int main(void) {
int n;
struct list list = { 0, 0 };
printf("Enter integers to add to list\n");
while(scanf("%d", &n) == 1 && n)
if(!makeNode(&list, n)) return perror("node"), EXIT_FAILURE;
printf("\n\n");
printf("You entered:\n");
printList(&list);
printf("\n\n");
printf("In reverse:\n");
printListReverse(&list);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
printf("You entered %d.\n", n);
deleteByPos(&list, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(&list);
insertionSort(&list);
printf("From top after sort:\n");
printList(&list);
printf("In reverse after Sort:\n");
printListReverse(&list);
return EXIT_SUCCESS;
}
*One would ideally free memory on exit.
It is usually much simpler to use a sentinel node rather than NULL to indicate the end of a list. So an empty list consists of a node whose head and tail point to itself. Once you add elements, sentinel->next is the first in the list and sentinel->prev is the last in the list. This removes many of the cases you have to test for NULL in your code:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node* top, node* newNode) {
node* current = top;
while (current->next != top &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
newNode->next->prev = newNode;
current->next = newNode;
current->next->prev = current;
}
void insertionSort(node* top) {
node* current = top->next;
// make top an empty ring so can append to it
top->next = top->prev = top;
while (current != top) {
node* next = current->next;
sortedInsert(top, current);
current = next;
}
}
node* deleteByPos(node* top,int position) {
int c = 0;
node* temp = top->next;
while (true) {
if (temp == top) {
printf("Reached end of list, position not available\n\n");
return top;
}
if (c == position) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
return top;
}
temp = temp->next;
c++;
}
}
node* makeNode(int n) {
node* np = malloc(sizeof(node));
np->data = n;
np->prev = np;
np->next = np;
return np;
}
void printList(node* top) {
for (node* np = top->next; np != top; np = np->next) {
printf("%d\n", np->data);
}
}
void printListReverse(node* top) {
for (node* np = top->prev; np != top; np = np->prev) {
printf("%d\n", np->data);
}
}
#endif /* driver_h */
main file :
#include "driver.h"
int main() {
int n;
node* np;
node* top;
top= makeNode(0);
printf("Enter integers to add to list\n");
do {
if (scanf_s("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
np->prev = top->prev;
top->prev = np;
top->prev->next = top;
np->prev->next = np;
}
} while (n != 0);