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;
}
我不明白为什么您需要使用指针来更改头部,但是如果您想在其他地方添加元素,则只需发送node* head
而不是{{1} }。就像node** head
insertatLast
一样,因为论点有效,但是如果我对node*head
做同样的事情,那不会。
答案 0 :(得分:1)
同时使用insertAtTop
和insertAtLast
可以同时实现pass by reference
和pass by value
。我建议您阅读difference between pass by reference and pass by value。您还可以阅读this。
我假设head
被声明为node* head;
通过引用传递:
void insertAtTop(node** head, int value){
node* temp=new node();
temp->data=value;
temp->next=*head;
*head=temp;
}
致电:insertAtTop(&head, value);
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;
}
致电:insertAtLast(&head, value);
按值传递:
node* insertAtTop(node* head, int value){
node* temp=new node();
temp->data=value;
temp->next= head;
head = temp;
return head;
}
致电:head = insertAtTop(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 = insertAtLast(head, value);
答案 1 :(得分:0)
您不必使用双指针。请参见下面的代码:
node* front(int n, node* head)
{
node *tmp = new node;
tmp -> data = n;
tmp -> next = head;
head = tmp;
return head;
}
答案 2 :(得分:0)
使用双指针,您可以将指针传递给指针。当您只有一个指针时,对其取消引用将为您提供变量的值。使用双指针,解引用可为您提供变量在内存中的地址。将节点添加到列表的最前面时,您将使用已经为头节点创建的节点,并传递指向它的指针的地址。而要添加到链表头的原因是必须这样做的原因是,由于链表结构被定义为具有最初指向null的头节点,因此您已经在内存中某个位置引用了链表的头。以及列表顶部的后续添加项将更改查找该链接列表开始位置的位置。
答案 3 :(得分:0)
两者中都有一个双指针。从这两个函数来看这两行:
*head=temp; // from insertAtTop
head->next=temp; // from insertAtLast
请注意,head->next = temp
可以等效地写为(*head).next = temp
。
那里有一个“双指针”:head
是指向结构的指针,并且该结构包含指针next
。基本上这两个图片:
*head = temp
的图表:
head --> [ *--]---> old_head
^
`-- temp is stored here, replacing the old_head
head->next = temp
或(*head).next = temp
的图表。出于示例的目的,节点结构被表示为三个存储单元,其中第三个是next
字段。确切的内存详细信息取决于您的编译器以及如何定义结构!
head --> [ ]
[ ]
[ *--]--> old_next
^
`-- temp is stored here, replacing old_next
基本上,唯一的区别是您拥有一个结构而不是一个指针对象。
在两种情况下,都将更新指针以引用新插入的节点。在insertAtTop
情况下,我们必须替换代表列表本身的那个指针。我们将列表对象表示为指向第一个节点的指针。如果列表已更改,使其具有不同的第一个节点,则该指针必须更改。在列表中的其他位置插入时,我们必须更新前一个节点的next
指针以指向新节点,因此我们将其分配给(*head).next
。
我们可以重写insertAtLast
以将insertAtTop
用作子例程:
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;
}
如果您跟踪对insertAtHead
的调用中发生了什么,您会发现它与我们替换的代码完全相同。我们取出了这段代码:
node* new_node=new node();
new_node->data=value;
new_node->next=NULL;
h->next=new_node;
但这与insertAtHead
的正文几乎相同:
node* temp=new node();
temp->data=value;
temp->next=*head;
*head=temp;
我们将表达式&h->next
的值作为head
参数传递。因此temp->next = *head
实际上是temp->next = *&h->next
,其中*&
被抵消,剩下temp->next = h->next
。但是我们知道h->next
是NULL
:我们的while
循环确保了这一点。因此,这实际上是temp->next = NULL
。
当然,*head = temp
与*(&h->next) = temp
是h->next = temp
一样。