c - 为什么我们不能在单链表的追加/插入函数的函数参数中使用单个指针?
问题描述
所以我一直在使用 C 中的指针学习数据结构,我对为什么我们使用双指针作为函数参数以及为什么我们不能在单链表的 append 函数中使用单个指针有疑问?(仍然是初学者)
#include<stdio.h>
#include<stdlib.h>
struct node
{
int number;
struct node *next;
};
void insert(struct node **q,int value)//this is the part where I have the doubt
{
struct node *temp,*r;
temp=*q;
if(*q==NULL)
{
temp=(struct node*)malloc(sizeof(struct node));
temp->number=value;
temp->next=NULL;
*q=temp;
}
else
{
temp=*q;
while(temp->next!=NULL)
temp=temp->next;
r=(struct node*)malloc(sizeof(struct node));
r->number=value;
r->next=NULL;
temp->next=r;
}
}
void print(struct node *temp)
{
printf("\n");
while(temp!=NULL)
{
printf("%d\n",temp->number);
temp=temp->next;
}
}
int main()
{
struct node *head;
head=NULL;
insert(&head,10);//call by reference
insert(&head,20);//call by reference
insert(&head,30);//call by reference
insert(&head,40);//call by reference
print(head);
return 0;
}
上面的代码工作得很好,但是当我使用单指针作为参数时,它会执行但没有输出。这是插入/追加函数的单指针参数版本。基本上为什么它不适用于单个指针?, 为什么我们需要使用双指针作为参数才能使其工作?
void insert(struct node *q,int value)
{
struct node *temp,*r;
temp=q;
if(q==NULL)
{
temp=(struct node*)malloc(sizeof(struct node));
temp->number=value;
temp->next=NULL;
q=temp;
}
else
{
temp=q;
while(temp->next!=NULL)
temp=temp->next;
r=(struct node*)malloc(sizeof(struct node));
r->number=value;
r->next=NULL;
temp->next=r;
}
}```
解决方案
在函数中,您试图更改指向列表头节点的指针。
如果函数将像第二个函数定义中那样按值接受指针,则该函数将处理指向头节点的原始指针值的副本。更改副本不会影响原始指针。原始指针将保持不变。
您可以想象(第二个)函数定义及其调用方式如下。
struct node *head;
head=NULL;
insert( head, 10 );
//...
void insert( /*struct node *q,int value */ )
{
struct node *q = head;
int value = 10;
//..
如您所见,该函数处理其自己的局部变量(函数参数是函数局部变量),该变量具有main 中定义q
的指针值的副本。head
因此,在函数中q
,获得新值的是局部变量。指针头的值没有被改变。
所以你需要通过引用传递指针。在 C 中,通过引用传递一个对象意味着传递一个指向该对象的指针,该对象是使用该指针间接传递给一个函数的。
但无论如何,函数定义都是不好的。当内存分配失败时,可以更简单地定义它并且没有未定义的行为。例如
int insert( struct node **head, int value )
{
struct node *new_node = malloc( sizeof( struct node ) );
int success = new_node != NULL;
if ( success )
{
new_node->number = value;
new_node->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = new_node;
}
return success;
}
如果不通过引用将指针传递给头节点,则需要从函数中返回指针的新值。在这种情况下,函数看起来像
struct node * insert( struct node *q, int value )
{
struct node *new_node = malloc( sizeof( struct node ) );
if ( new_node != NULL )
{
new_node->number = value;
new_node->next = NULL;
if ( q == NULL )
{
q = new_node;
}
else
{
struct node *current = q;
while ( current->next != NULL ) current = current->next;
current->next = new_node;
}
}
return q;
}
在这种情况下,必须在列表为空时第一次调用该函数,方法如下
head = insert( head, 10 );
推荐阅读
- java - 如何使用 aws aws-codebuild、codedeploy、cloudformation 的服务为 aws lambda 与 java 配置持续集成
- docker - 将 AWS Codebuild 环境变量注入 Dockerfile
- ruby-on-rails - 如何在选择选项(simple_form rails)中添加价值?
- javascript - 如何在javascript中提示shell命令的执行状态?
- c++ - 类有一个 selftype 的对象
- python - 尝试使用一个类,但在 Kivy 中出现 NoneType 错误
- sql - 如何计算两个日期列的出现次数并仅在一张表中显示?
- image - 从单元格中删除图像并显示新单元格高度的问题
- python - 如何逐行打印命令 output.txt
- c++ - 鼠标单击 QSpinBox::validate 中显示的工具提示会导致崩溃