问题
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