【问题标题】:Find cardinal number of a list in C在C中查找列表的基数
【发布时间】:2021-03-14 11:08:03
【问题描述】:

如何只找到列表中出现一次的元素并返回基数?例如,如果我的列表包含 {3,2,1,1,2,4},我希望返回的计数器为4 而不是 6,因为我们不计算重复的数字。 这是我目前写的代码。

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;
} 

【问题讨论】:

  • 标有“//do what?”的地方没有什么可以填写的这将使该功能无需更改其他代码即可工作。这是因为那些地方的代码属于“如果ptr1->data被重复,那么……”,但是你需要计算那些重复的东西,所以你需要在上面写着“如果ptr1->data 重复,则计算它”的代码。想一想如何做到这一点。
  • 另外,避免编写像int counter; 这样不会初始化它定义的对象的代码。初始化对象,除非有充分的理由不这样做。使用int counter = 0;。如果你不从零开始(或其他已知的起点),你就不能计算任何东西。

标签: c linked-list unique singly-linked-list function-definition


【解决方案1】:

你的函数实现是错误的。

即使是第一个while循环中的条件

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

不正确,因为如果列表只包含一个节点,则不会执行循环,函数将返回 0。

并且在函数内变量counter 没有被改变。

这是一个演示程序,展示了如何实现函数Find_cardinal(更适合命名为count_distinct)。

#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;
}

程序输出是

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

【讨论】:

    【解决方案2】:

    你不能使用你当前的构造来做到这一点。这个想法是遍历列表并“记住”或检查特定项目是否重复,因此您需要以某种方式存储已传递的唯一值。下面是一个简单的实现。
    示例输出:

    Input values
    3
    2
    1
    1
    2
    4
    
    Unique count: 4
    

    代码:

    #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;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-10
      相关资源
      最近更新 更多