Home > front end >  Delete a prime number in a doubly linked list
Delete a prime number in a doubly linked list

Time:10-02

#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.

CodePudding user response:

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.

CodePudding user response:

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