C++ 为什么需要一个双指针来更改head而不是链接列表中的其他位置
我不明白为什么需要使用指向指针的指针来更改头部,但如果要在其他位置添加元素,只需发送C++ 为什么需要一个双指针来更改head而不是链接列表中的其他位置,c++,C++,我不明白为什么需要使用指向指针的指针来更改头部,但如果要在其他位置添加元素,只需发送node*head,而不是node**head。类似于insertAtTopnode*head作为参数工作,但如果我对insertAtTop做了同样的操作,则不会。通过使用按引用传递和按值传递可以同时实现insertAtTop。我建议你读书。你也可以阅读 我假设head被声明为node*head 通过引用传递: void insertAtTop(node** head, int value){ node*
node*head
,而不是node**head
。类似于insertAtTop
node*head
作为参数工作,但如果我对insertAtTop
做了同样的操作,则不会。通过使用按引用传递和按值传递可以同时实现insertAtTop
。我建议你读书。你也可以阅读
我假设head
被声明为node*head代码>
通过引用传递:
void insertAtTop(node** head, int value){
node* temp=new node();
temp->data=value;
temp->next=*head;
*head=temp;
}
void insertAtLast(node*head, int value){
while(head->next!=NULL){
head=head->next;
}
node*temp=new node();
temp->data=value;
temp->next=NULL;
head->next=temp;
}
void insertAtLast(node** head, int value){
node* h = *head;
while(h->next!=NULL){
h = h->next;
}
node* new_node=new node();
new_node->data=value;
new_node->next=NULL;
h->next=new_node;
}
调用:insertAtTop(&head,value)代码>
调用:insertaltlast(&head,value)代码>
传递值:
void insertAtTop(node** head, int value){
node* temp=new node();
temp->data=value;
temp->next=*head;
*head=temp;
}
void insertAtLast(node*head, int value){
while(head->next!=NULL){
head=head->next;
}
node*temp=new node();
temp->data=value;
temp->next=NULL;
head->next=temp;
}
void insertAtLast(node** head, int value){
node* h = *head;
while(h->next!=NULL){
h = h->next;
}
node* new_node=new node();
new_node->data=value;
new_node->next=NULL;
h->next=new_node;
}
调用:head=insertatop(head,value)代码>
调用:head=insertlast(head,value)代码>您不必使用双指针。请参阅下面的代码:
node* insertAtLast(node* head, int value){
node* original_head = head;
while(head->next!=NULL){
head=head->next;
}
node*temp=new node();
temp->data=value;
temp->next=NULL;
head->next=temp;
return original_head;
}
使用双指针时,将指针传递给指针。当您只有一个指针时,取消对它的引用会给出变量的值。使用双指针,解引用将为您提供内存中变量的地址。当您将节点添加到列表的前面时,您将获取已经为head节点创建的节点,并传入指向它的指针的地址。为了添加到链表的头部,你必须这样做的原因是,你已经在内存中的某个地方有了一个指向链表头部的引用,因为链表结构被定义为有一个最初指向null的头部节点,随后添加到链表前面的节点将改变查找位置链接列表的开始 两者都有一个双指针。从两个函数中看这两条类似的线:
node* front(int n, node* head)
{
node *tmp = new node;
tmp -> data = n;
tmp -> next = head;
head = tmp;
return head;
}
请注意,head->next=temp
可以等效地写成(*head)。next=temp
那里有一个“双指针:head
是指向结构的指针,该结构包含一个指针next
。基本上这两幅图:
*压头=温度的示意图
:
*head=temp; // from insertAtTop
head->next=temp; // from insertAtLast
head->next=temp
或(*head.)的图表。next=temp
。例如,节点结构表示为三个存储单元,其中第三个是next
字段。确切的内存细节取决于编译器和定义结构的方式
head --> [ *--]---> old_head
^
`-- temp is stored here, replacing the old_head
基本上,唯一的区别是我们有一个结构,而不仅仅是一个指针对象
在这两种情况下,都会更新指针以引用新插入的节点。在insertAtTop
案例中,我们必须替换表示列表本身的指针。我们将列表对象表示为指向第一个节点的指针。如果更改列表以使其具有不同的第一个节点,则该指针必须更改。在列表中的其他位置插入时,我们必须更新上一个节点的next
指针以指向新节点,因此我们将指定给(*head).next
我们可以重写insertAtLast
以将insertAtTop
用作子例程:
head --> [ ]
[ ]
[ *--]--> old_next
^
`-- temp is stored here, replacing old_next
如果您跟踪调用insertatead
时发生的情况,您会发现它所做的事情与我们替换的代码完全相同。我们删除了以下代码:
node* insertAtLast(node* head, int value){
/* find the insertion point */
node* original_head = head;
while(head->next!=NULL){
head=head->next;
}
/* now treat that as the head */
(void) insertAtTop(&head->next, value);
return original_head;
}
但这几乎与insertatead
的主体相同,即:
node* new_node=new node();
new_node->data=value;
new_node->next=NULL;
h->next=new_node;
我们将表达式&h->next
的值作为head
参数传递。所以temp->next=*head
实际上是temp->next=*&h->next
中的*&code>取消,留下temp->next=h->next
。但是我们知道h->next
是NULL
:我们的while
循环确保了这一点。这就是有效的temp->next=NULL
。
当然,*head=temp
与*(&h->next)=temp
相同,即h->next=temp
相关/重复:在c++
中,应该使用void insertatop(node*&head,int-value){
相反。我不明白为什么需要使用指向指针的指针来更改标头,但如果要在其他位置添加元素,只需发送node*
head而不是node**
head即可。使用node*
时,您是按值传递指针。传递值时,它是一个副本。更改副本对调用函数没有影响。请查看调用代码。您传入了一个头指针。在前面插入一个新节点后,应该是什么?如果在头之后插入一个新节点,情况是否相同?注意。这是使用sentinel节点(下一个=头)的原因之一可以很好:它使大多数操作(包括此操作)更加规则,具有更少的特殊角盒。请尝试Ram。但是对head
内部front()
所做的更改将只保留在front()
中。从front()返回后,这些更改将不会保留
。哦,是的,我的错!你应该把脑袋还给我吗?是的。请看看我的答案。
node* temp=new node();
temp->data=value;
temp->next=*head;
*head=temp;