单链表,main函数的一个小问题
Singly linked list, A small problem in main function
编写此程序以删除排序链表中具有相同数据的节点,但 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---%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
编写此程序以删除排序链表中具有相同数据的节点,但 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---%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