无表头链表队列enqueue函数中Node**双指针的作用与含义解析
理解无表头链表队列中的
Node **list双指针 先明确:Node **list是指向指针的指针,用它的核心原因是C语言的参数传递是「值传递」——如果函数要修改调用者传入的指针变量本身(而不是指针指向的内容),就必须传这个指针的地址,也就是指针的指针。
为什么必须用双指针?
假设我们不用Node **list,而是用Node *list作为enqueue的参数:
- 当队列为空时,函数里给
list赋值new,但这个list只是原头指针的一个副本,修改副本不会影响调用者那边的原头指针。函数结束后,外面的头指针还是NULL,新节点根本没被正确关联到队列上,队列等于白初始化了。
而用Node **list时,*list就直接对应调用者那边的头指针变量:
- 队列为空时,
*list = new直接把调用者的头指针改成指向新节点,这样外部的队列头指针就正确指向了第一个节点。 - 非空时,
new = *list拿到队列的头指针副本,遍历到链表尾部后调用insertNode插入新节点,这时候虽然没修改头指针,但通过*list能正确访问到队列的起始位置。
结合代码细节解释
补全必要定义后的完整代码示例:
#include <stdlib.h> typedef struct Node { int val; struct Node *next; } Node; // 判断队列是否为空 int isEmpty(Node *list) { return list == NULL; } void insertNode(Node * prev,int x) { Node * new = (Node *) malloc(sizeof(Node)); new->val = x; new->next = prev->next; prev->next = new; } void enqueue(Node ** list, int x) { Node * new = (Node *) malloc(sizeof(Node)); if (isEmpty(*list)) { *list = new; (*list)->val = x; (*list)->next = NULL; } else { new = *list; while (new->next != NULL) new = new->next; insertNode(new,x); } }
isEmpty(*list):这里*list取出双指针指向的内容,也就是队列的头指针,判断是否为空。*list = new:直接修改调用者的头指针变量,让它指向新创建的节点,完成空队列的初始化。- 非空分支里,
new = *list拿到头指针的副本,遍历到链表最后一个节点,然后调用insertNode在尾部插入新节点——这时候只修改尾部节点的next,不需要改动头指针,但双指针的传递方式保证了我们能正确获取队列的起始位置。
总结一下:Node **list的作用就是让函数能够修改调用者那边的队列头指针变量,这是无表头节点链表队列初始化时必须的操作,因为空队列的头指针是NULL,第一次入队必须把它改成指向第一个节点。
内容的提问来源于stack exchange,提问作者dev0419
相关产品推荐
相关产品推荐

