我在C:
中实现了一个带有Pop功能的Linked-ListNode * pop (Node * head) {
Node * temp = head;
printf("Temp is: %s\n", temp->val);
if (head->next != NULL) {
*head = *head->next;
}
printf("Temp is: %s\n", temp->val);
return temp;
}
当我弹出时的输出将是:
Temp is: node1 value
Temp is: node2 value
也就是说,当我指定*head = *head->next
时,临时正在变得临时 - >接下来。
那么如何获取当前head
的值并将其返回,同时将链接列表的头部移动到head->next
?
执行head = head->next
不会删除对第一个节点的引用。 (即当我打印列表时,第一个节点仍然存在)。
感谢。
答案 0 :(得分:3)
首先,请注意您的代码(以及一些以前的解决方案)永远不会弹出列表中的最后一个元素。你想要
if (*head != NULL) ...
接下来,将指针传递给指针将起作用。但实际上制作这样的列表标题更好:
typedef struct node_s {
struct node_s *next;
... data declaration here
} Node;
typedef struct list_s {
struct node_s *head;
} List;
void init_list(List *list) {
list->head = NULL;
}
现在声明一个这样的列表:
List list[1];
init_list(list);
声明一个元素的数组会自动引用list
一个指针,从而消除了代码中的大量&
个。然后实现推送和弹出很好很干净:
void push(List *list, Node *node) {
node->next = list->head;
list->head = node;
}
Node *pop(List *list) {
Node *head = list->head;
if (head) {
list->head = head->next;
head->next = NULL;
}
return head;
}
为什么这样更好?假设您稍后决定在列表中保留项目数。使用单独的标头节点,这非常简单:
typedef struct list_s {
struct node_s *head;
int length;
} List;
void init_list(List *list) {
list->head = NULL;
length = 0;
}
void push(List *list, Node *node) {
node->next = list->head;
list->head = node;
++list->length;
}
Node *pop(List *list) {
Node *head = list->head;
if (head) {
list->head = head->next;
head->next = NULL;
--list->length;
}
return head;
}
注意不需要更改调用代码。随着指针接近指针,你处于死胡同。还有许多其他用例,其中有一个单独的列表标题可以使您的代码更灵活,以便将来进行更改。
答案 1 :(得分:2)
您需要为您的函数传递head
的地址才能对其进行修改。然后你的函数需要取消引用这个地址。此外,最后一个pop()也需要更改* AddressOfHead
Node *pop(Node **AddressOfHead) {
Node *temp = *AddressOfHead;
if (temp) {
*AddressOfHead = temp->next;
}
return temp;
}
...
// Usage example
Node *TopOfList = pop(&Head);
答案 2 :(得分:1)
指针按值传递。也就是说,当您将指针传递给堆栈时,调用函数中指针指向的内容的更改不会反映在调用函数中。
为了在调用函数中更改节点指针的值,您需要将堆栈作为指针传递给指针:
Node* pop (Node** head) {
Node* temp = *head;
if (temp) {
*head = temp->next; // to update stack in calling function
temp->next = NULL; // to detach temp from the rest of the list
}
return temp;
}
在更新if ((*head)->next)
的值之前,您不需要检查if (temp->next)
或本例*head
,因为如果您位于堆栈的最后一个节点并且下一个节点是NULL
,您希望列表无论如何都是NULL
。
Karthik T的答案正确解释了为什么temp
的价值在原始代码中发生了变化。
答案 3 :(得分:1)
其他人告诉你如何修复它,让我回答为什么temp
改变了..
Node * pop (Node * head) {
您正在将head
作为指向Node
的指针。
因此当你这样做时
*head = *head->next;
我认为它被解析为
*head = *(head->next);
然后将下一个对象复制到head
的对象中,该对象在temp
处是同一个对象。
答案 4 :(得分:0)
void pop(struct node** tol) {
struct node* t = *tol;
while (t->link->link != NULL){
t = t->link;
}
t->link = NULL;
}