编写此程序以删除排序链表中具有相同数据的节点,但while
循环没有按预期执行。通过使用一些printf
语句,我发现while循环只执行了一次,而if条件并没有执行,则执行第一次之后的语句。你能回答我为什么会发生这种情况吗?我该如何解决?
注意:Insert
和Print
函数是用户定义的函数。
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