我问你一个问题,因为我正在做的作业没有成功。该结构是一个常见的链表,在main中声明头指针,并将头指针的地址值作为参数传递给函数。全局变量top用于确定当前数据的位置。
下面当前的代码在执行时只会检测到错误。
结构:
struct ListNode{
int data;
struct ListNode* link;
};
int top = 0;
代码:
void DisplayList(ListNode** head){
if(*head == NULL){
printf("List = Emptyn");
}
else{
printf("List = ");
for(;(*head) != NULL; *head = (*head)->link){
printf("%d ",(*head)->data);
}
}
printf("n");
}
void AddList(ListNode** head){
ListNode* temp = (ListNode*)malloc(sizeof(ListNode));
int num;
printf("Data register) ");
scanf("%d",&num);
temp->data = num;
temp->link = NULL;
top++;
if(*head == NULL){
*head = temp;
}
else{
for(;(*head)->link != NULL; *head = (*head)->link){}
(*head)->link = temp;
}
DisplayList(head);
}
预期结果:
数据寄存器(10列表=10
数据寄存器(20列表=10 20
数据寄存器(30列表=10 20 30
您不应该在循环中修改*head
。您需要使用一个局部变量来遍历列表,否则您将更改调用者的变量以指向列表的末尾。
void DisplayList(ListNode** head){
if(*head == NULL){
printf("List = Emptyn");
}
else{
printf("List = ");
for(ListNode *step = *head;step != NULL; step = step->link){
printf("%d ",step->data);
}
}
printf("n");
}
void AddList(ListNode** head){
ListNode* temp = (ListNode*)malloc(sizeof(ListNode));
int num;
printf("Data register) ");
scanf("%d",&num);
temp->data = num;
temp->link = NULL;
top++;
if(*head == NULL){
*head = temp;
}
else{
ListNode *step = *head;
for(;step->link != NULL; step = step->link){}
step->link = temp;
}
DisplayList(head);
}
您的错误在于如何遍历列表:
for(; (*head)->link != NULL; *head = (*head)->link) {}
一开始,*head
是来自调用函数的列表的头。通过分配给它,可以连续覆盖它,直到它变为null。
相反,您应该分配给head
:它首先保存调用函数中头节点的地址,然后在后续迭代中保存上一个节点的link
指针的地址:
for(; (*head)->link != NULL; head = &(*head)->link) {}
在这个循环之后,head
保存指针的地址,新节点应该存储在该地址。将新节点直接分配给该指针:
*head = temp;
当列表为空时,这将更新调用函数的头指针,否则将更新上一个节点的link
成员。你不必特别处理列表为空的情况。
插入功能现在可能如下所示:
void AddList(ListNode** head, int num)
{
ListNode* temp = malloc(sizeof(ListNode));
temp->data = num;
temp->link = NULL;
while (*head) head = &(*head)->link);
*head = temp;
}
(在我看来,读取输入和打印列表不应该是插入功能的一部分。(
关于您的打印功能:看到这样的功能:
void DisplayList(ListNode** head)
引发一个危险信号:将指针传递给节点指针表示您想要修改列表(您无意中这样做了(,但打印列表只会检查它。将签名更改为
void DisplayList(const ListNode* head)
则在函数中使用CCD_ 7而不是CCD_。(经验法则:如果您从未在列表中的某个位置使用*head = ...
,则不需要指向节点指针的指针。(