c-单链表,主函数中的一个小问题



编写此程序以删除排序链表中具有相同数据的节点,但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---%cn", 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可以调用未定义的行为,因为函数中没有检查传递的指针是否等于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, "%ct", 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

相关内容

  • 没有找到相关文章

最新更新