当在下面的交叉函数中进行第一次push调用时,tail-> next的值为NULL。我的理解是& tail-> next然后指向堆栈上的虚拟对象的最后4个字节,它保存指向next的指针。现在当push函数内部更改head_ref时,我们是否更改了存储在虚拟对象的下一个变量中的地址?所以在我看来,dummy总是指向列表的最后一个元素,即使这在执行时正确输出了列表的头部。有人可以解释每次推送呼叫在内存中发生的情况吗?感谢。
此问题取自here
struct node* sortedIntersect(struct node* a, struct node* b)
{
struct node dummy;
struct node* tail = &dummy;
dummy.next = NULL;
while (a != NULL && b != NULL)
{
if (a->data == b->data)
{
push((&tail->next), a->data);
tail = tail->next;
a = a->next;
b = b->next;
}
else if (a->data < b->data) /* advance the smaller list */
a = a->next;
else
b = b->next;
}
return(dummy.next);
}
void push(struct node** head_ref, int new_data)
{
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
答案 0 :(得分:0)
对push
的第一次调用确实会改变虚拟对象的下一个指针,但随后tail
会提前指向刚按下的元素(tail = tail->next
)。因此,下一个push
对该节点的next
进行操作,而不是虚拟节点。
答案 1 :(得分:0)
假人开始像这样:
______ ______
|dummy| -> |NULL|
| 0 | | |
------- ------
在第一次致电push(&tail->next, a->data)
之后,我将假设a->data
为5
,这将使您失望(请记住tail
指向{dummy
1}}此时):
______ _________ _____
|dummy| -> |new_node| -> |NULL|
| 0 | | 5 | | |
----- --------- ------
然后我们致电tail = tail->next;
,这会导致tail
指向new_node
,这就是为什么我们再次致电push(&tail->next, a->data)
,new_node
2号将插入旧new_node
和NULL
最后,我们调用return dummy->next
,它将返回链接列表,其中最近添加的节点位于第一位。虚拟本身将被删除,因为它是在堆栈上分配的。
push
函数变得更加清晰,如果我们这样写的话:
void push(struct node** head_ref, int new_data)
{
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
new_node->data = new_data;
/* save old head */
struct node* old_head = *head_ref;
/* move the head to point to the new node */
*head_ref = new_node;
/* link the old list off the new node */
new_node->next = old_head;
}