Find cardinal number of a list in C

|▌冷眼眸甩不掉的悲伤 提交于 2020-12-27 06:31:39

问题


How can i find only the elements that appears once in the list and return the cardinal number?For example if my list consist of {3,2,1,1,2,4} i expect for return the counter to be 4 and not 6 cause we do not count the duplicate numbers. Here is the code that i have written so far.

struct Node 
{ 
    int data;  
    struct Node *next; 
}; 
  
int Find_cardinal(struct Node *start) 
{ 
    struct Node *ptr1, *ptr2
    ptr1 = start; 
    int counter=0;
    /* Pick elements one by one */
    while (ptr1 != NULL && ptr1->next != NULL) 
    { 
        ptr2 = ptr1; 
  
        /* Compare the picked element with rest 
           of the elements */
        while (ptr2->next != NULL) 
        { 
            /* If duplicate */
            if (ptr1->data == ptr2->next->data) 
            { 
                break;
            } 
            else 
                //do what?
                ptr2 = ptr2->next; 
                
        } 
        ptr1 = ptr1->next; 
    } 
    return counter;
} 

回答1:


Your function implementation is wrong.

Even the condition in the first while loop

while (ptr1 != NULL && ptr1->next != NULL)

is incorrect because if the list contains only one node the loop will not be executed and the function will return 0.

And within the function the variable counter is not being changed.

Here is a demonstrative program that shows how the function Find_cardinal that is better to name like count_distinct can be implemented.

#include <stdio.h>
#include <stdlib.h>

struct Node 
{ 
    int data; 
    struct Node *next; 
}; 
typedef struct Node Node_t;

size_t assign( Node_t **head, const int a[], size_t n )
{
    while ( *head )
    {
        Node_t *tmp = *head;
        head = &( *head )->next;
        free( tmp );
    }
    
    size_t i = 0;
    
    for ( ; i < n && ( *head = malloc( sizeof( Node_t ) ) ) != NULL; i++ )
    {
        ( *head )->data = a[i];
        ( *head )->next = NULL;
        head = &( *head )->next;
    }
    
    return i;
}

size_t count_distinct( const Node_t *head )
{
    size_t n = 0;
    
    for ( const Node_t *current = head; current != NULL; current = current->next )
    {
        const Node_t *prev = head;
        
        while ( prev != current && prev->data != current->data )
        {
            prev = prev->next;
        }
        
        if ( prev == current ) ++n;
    }
    
    return n;
}

FILE * display( const Node_t *head, FILE *fp )
{
    for ( ; head != NULL; head = head->next )
    {
        fprintf( fp, "%d -> ", head->data );
    }
    
    fputs( "null", fp );
    
    return fp;
}

int main(void) 
{
    Node_t *head = NULL;
    int a[] = { 1, 2, 1, 1, 3, 4 };
    
    assign( &head, a, sizeof( a ) / sizeof( *a ) );
    
    fputc( '\n', display( head, stdout ) );
    
    printf( "There are %zu distinct data in the list.\n", count_distinct( head ) );
    
    return 0;
}

The program output is

1 -> 2 -> 1 -> 1 -> 3 -> 4 -> null
There are 4 distinct data in the list.



回答2:


You cannot do it using your current construct. The idea is to iterate through the list and 'remember' or check whether a particular item is duplicate, so somehow you need to store the unique values that have been passed. Below is one naive implementation.
Sample output:

Input values
3
2
1
1
2
4

Unique count: 4

Code:

#include <stdio.h>
#include <stdlib.h>

struct Node
{
    int data;
    struct Node *next;
};

void printAll(struct Node *start){
    struct Node *ptr1;
    ptr1 = start;
    while (ptr1 != NULL) {
        printf("%d\n", ptr1->data);
        ptr1 = ptr1->next;
    }
}

int countUnique(struct Node *start) {
    struct Node *uniqueNodes; //this will hold the unique value
    struct Node *ptrInput;
    ptrInput = start;
    int counter = 0;
    /* Pick elements one by one */
    while (ptrInput != NULL) {
        //Loop through the list which hold the unique value
        struct Node *ptrUnique;
        ptrUnique = uniqueNodes;
        int isFound = 0;

        while (ptrUnique != NULL && !isFound) {
            if (ptrInput->data == ptrUnique->data) {
                isFound = 1; //value is found in the unique list
            } //end if
            ptrUnique = ptrUnique->next;
        } //end while

        if (! isFound) { //when not found, then need to add the value in the unique list and increment the counter afterwards
            struct Node *newNode = (struct Node *) malloc (sizeof(struct Node));
            newNode->data = ptrInput->data;
            newNode->next = NULL;

            //If uniqueNodes is still empty, then just change the pointer of the uniqueNodes to the newly created item.
            //Otherwise, just put the newly created item on the head of the list
            if (uniqueNodes == NULL) {
                uniqueNodes = newNode;
            } else {
                newNode->next = uniqueNodes;
                uniqueNodes = newNode;
            } //end else

            counter++;
        } //end if

        ptrInput = ptrInput->next;
    } //end while
    return counter;
}

int main(void) {
    struct Node *node1 = (struct Node *) malloc (sizeof(struct Node));
    struct Node *node2 = (struct Node *) malloc (sizeof(struct Node));
    struct Node *node3 = (struct Node *) malloc (sizeof(struct Node));
    struct Node *node4 = (struct Node *) malloc (sizeof(struct Node));
    struct Node *node5 = (struct Node *) malloc (sizeof(struct Node));
    struct Node *node6 = (struct Node *) malloc (sizeof(struct Node));

    node1->data = 3;
    node2->data = 2;
    node3->data = 1;
    node4->data = 1;
    node5->data = 2;
    node6->data = 4;

    node1->next = node2;
    node2->next = node3;
    node3->next = node4;
    node4->next = node5;
    node5->next = node6;
    node6->next = NULL;

    printf("Input values\n", NULL);
    printAll(node1);
    int uniq = countUnique(node1);
    printf("\nUnique count: %d\n", uniq);
    return 0;
}


来源:https://stackoverflow.com/questions/65108956/find-cardinal-number-of-a-list-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!