为何链表尾插函数需返回head?数组同类操作却无需返回?
链表尾插返回head指针与数组插入的差异解析
一、为什么链表尾插函数要返回head并重新赋值?
你提供的示例代码里,链表已经有初始节点,尾插只是修改最后一个节点的next指针,head本身的值确实没变化,但这种返回head的写法是通用兼容的处理方式:
- 当链表是空链表(
head == NULL)时,第一次插入节点需要让head指向新节点,此时函数必须返回新节点的地址,否则主函数里的head还是NULL,无法访问新创建的链表。 - C语言是值传递,函数参数里的
head是主函数head的副本。如果要修改主函数中head的指向(比如空链表插入),要么通过返回值让主函数重新赋值,要么用二级指针操作。
比如给你的尾插函数补上空链表的处理,就能看到返回head的必要性:
struct node *insertAtEnd(struct node *head, int data) { struct node *ptr = (struct node *)malloc(sizeof(struct node)); ptr->data = data; ptr->next = NULL; // 空链表情况:新节点就是头节点 if (head == NULL) { return ptr; } struct node *p = head; while (p->next != NULL) { p = p->next; } p->next = ptr; return head; }
二、为什么数组的插入操作不需要返回值?
- C语言中数组名作为函数参数时,会自动退化为指向数组第一个元素的指针。函数通过这个指针可以直接修改数组内存中的元素,因为指针指向的是数组的实际存储位置。
- 数组在内存中是连续存储的,它的起始地址一旦确定就不会改变(即使是动态分配的数组,常规插入操作也不需要修改起始地址,扩容是另一种场景)。所以函数直接修改数组元素即可,不需要返回新的指针。
三、用二级指针实现无返回值的尾插
正如你想到的,用二级指针(存储指针的地址)可以直接修改主函数里的head指针,不需要返回值:
void insertAtEnd(struct node **head, int data) { struct node *ptr = (struct node *)malloc(sizeof(struct node)); ptr->data = data; ptr->next = NULL; if (*head == NULL) { *head = ptr; // 直接修改主函数中head的指向 return; } struct node *p = *head; while (p->next != NULL) { p = p->next; } p->next = ptr; }
调用时直接传入head的地址即可,不需要重新赋值:
insertAtEnd(&head, 88);
参考代码
main函数中直接实现尾插的代码:
struct node *newNode; newNode = malloc(sizeof(struct node)); newNode->data = 4; newNode->next = NULL; struct node *temp = head; while(temp->next != NULL){ temp = temp->next; } temp->next = newNode;
封装为函数的代码:
struct node *insertAtEnd(struct node *head, int data) { struct node *ptr = (struct node *)malloc(sizeof(struct node)); ptr->data = data; struct node *p = head; while (p->next != NULL) { p = p->next; } p->next = ptr; ptr->next = NULL; return head; } int main() { struct node *head; struct node *first; struct node *second; struct node *third; head = (struct node *)malloc(sizeof(struct node)); first = (struct node *)malloc(sizeof(struct node)); second = (struct node *)malloc(sizeof(struct node)); third = (struct node *)malloc(sizeof(struct node)); // fill data in head and point it to next node head->data = 69; head->next = first; // fill data in first and point it to next node first->data = 54; first->next = second; // fill data in second and point it to next node second->data = 33; second->next = third; // fill data in third and point it to null third->data = 36; third->next = NULL; printf("linked list before traversal : "); linkedListTraversal(head); printf("\n\nlinked list after traversal : "); head = insertAtEnd(head, 88); // a function to print all the data in linked list linkedListTraversal(head); return 0; }
个人思考
我们使用指针是为了对链表结构做永久修改,采用值传递方式。链表需返回指针并赋值给head,而数组无需返回,是因为数组仅修改元素数据,链表则修改地址值。也可使用双指针实现无返回值的函数,双指针即存储特定数据类型地址的地址的指针变量。
内容的提问来源于stack exchange,提问作者Prathmesh
相关产品推荐
相关产品推荐

