单链表,main函数的一个小问题

Singly linked list, A small problem in main function

编写此程序以删除排序链表中具有相同数据的节点,但 while 循环未按预期执行。通过使用一些 printf 语句,我发现 while 循环被执行了一次,但是第一个 if 条件之后的语句没有被执行。 你能回答我为什么会这样吗,我该如何解决这个问题?

注意 : InsertPrint 函数是用户定义的函数。

Insert(&Head,char data):每次调用都会在链表开头插入数据;

void Insert(struct Node **Head, char data)
{
    struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
    temp->data = data;
    temp->next = *Head;
    *Head = temp;
}

Print :取List头部,在输出终端打印链表。

void Print(struct Node *Head)
{
    printf("%c", Head->data);
    while (Head->next != NULL)
    {
        Head = Head->next;
        printf("\t%c", Head->data);
    } 
}

...

int main()
{
    struct Node *Head = NULL;
    Insert(&Head, '6');
    Insert(&Head, '5');
    Insert(&Head, '5');
    Insert(&Head, '5');
    Insert(&Head, '5');
    Insert(&Head, '5');
    Insert(&Head, '5');
    Insert(&Head, '4');
    Insert(&Head, '4');
    Insert(&Head, '3');
    Insert(&Head, '2');
    Insert(&Head, '1');
    Insert(&Head, '1');
    Insert(&Head, '1');

    printf("dta---%c\n", Head->data);
    Print(Head);

    //Code to deleate duplicate data  from a sorted singly linked list
    struct Node *PreviousHead = NULL;
    while (Head != NULL)
    {
        if (PreviousHead->data == Head->data) //i think there is some error in this statement...
        {
            while (PreviousHead->data == Head->data)
            {
                
                PreviousHead->next = Head->next;
                free(Head);
                Head = PreviousHead->next;
                if (Head == NULL)
                    break;
            }
        }
        
        PreviousHead = Head;
        Head = Head->next;

        if (PreviousHead->data == Head->data)
        {
            PreviousHead->next = Head->next;
            free(Head);
            Head = PreviousHead->next;
        }
    }
    Print(Head);
}

试试这个从单链表中删除重复项。 NULL 检查和不必要的代码有很多问题。

while (Head != NULL)
{
    struct Node *next = Head->next;

    while (next != NULL && Head->data == next->data) {
        Head->next = next->next;
        free(next)
        next = Head->next;
    }

    Head = Head->next;
}

对于初学者,您没有排序的链表。也就是说,通常用户可以按任何顺序在列表中输入值。

如果你想要一个排序链表你需要改变函数Insert,

节点的内存分配也可能会失败。你应该在函数内处理这种情况。

函数可以看成下面的样子。

int Insert( struct Node **head, char data )
{
    struct Node *temp = malloc( sizeof( struct Node ) );
    int success = temp != NULL;

    if ( success )
    {
        temp->data = data;
        
        while ( *head && !( data < ( *head )->data ) ) head = &( *head )->next;
        
        temp->next = *head;
        *head = temp;
    }
    
    return success;
}

函数 Print 如果函数的用户将传递一个空指针(一个空列表),函数 Print 可以调用未定义的行为,因为函数中没有检查传递的指针是否等于 NULL.所以这个声明

void Print(struct Node *Head)
{
    printf("%c", Head->data);
    ^^^^^^^^^^^^^^^^^^^^^^^

调用未定义的行为。

在您尝试删除重复项的 main 中,while 循环又会调用未定义的行为,因为最初指针 PreviousHead 设置为 NULL 并且此空指针用于访问内存

struct Node *PreviousHead = NULL;
while (Head != NULL)
{
    if (PreviousHead->data == Head->data)
        ^^^^^^^^^^^^^^^^^^

您应该像编写将节点插入列表的函数那样编写一个单独的函数。

这是一个演示程序,展示了如何编写所描述的函数。

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

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

int Insert( struct Node **head, char data )
{
    struct Node *temp = malloc( sizeof( struct Node ) );
    int success = temp != NULL;

    if ( success )
    {
        temp->data = data;
        
        while ( *head && !( data < ( *head )->data ) ) head = &( *head )->next;
        
        temp->next = *head;
        *head = temp;
    }
    
    return success;
}

FILE * Print( const struct Node *head, FILE *fp )
{
    for ( ; head != NULL; head = head->next )
    {
        fprintf( fp, "%c\t", head->data );
    }
    
    fputs( "null", fp );
    
    return fp;
}


void RemoveDuplicates( struct Node **head )
{
    struct Node *current = *head;
    
    while ( current && current->next )
    {
        if ( current->data == current->next->data )
        {
            struct Node *temp = current->next;
            current->next = current->next->next;
            free( temp );
        }
        else
        {
            current = current->next;
        }
    }
}

void clear( struct Node **head )
{
    while ( *head )
    {
        struct Node *temp = *head;
        *head = ( *head )->next;
        free( temp );
    }
}

int main(void) 
{
    struct Node *head = NULL;
    
    srand( ( unsigned int )time( NULL ) );
    
    const int N = 10;
    
    for ( int i = 0; i < N; i++ )
    {
        Insert( &head, '0' + rand() % N );
    }
    
    fputc( '\n', Print( head, stdout ) );
    
    RemoveDuplicates( &head );

    fputc( '\n', Print( head, stdout ) );

    clear( &head );
    
    fputc( '\n', Print( head, stdout ) );

    return 0;
}

程序输出可能看起来像

0   0   1   1   2   2   3   4   7   7   null
0   1   2   3   4   7   null
null