昨天我试图实现一个链表,虽然它有效但我“有点”了解,但它让我的脑子有点油腻。
这里的函数addNode()有什么问题?
#include <stdio.h>
struct Node
{
int value;
struct Node *next;
};
struct Node *createList();
void addNode(struct Node* head, int value); // Adds Node directly after head
void viewList(struct Node *head); // Outputs list starting from head
int main()
{
struct Node *head = createList();
addNode(head, 10);
addNode(head, 8);
addNode(head, 23);
addNode(head, 5);
addNode(head, 4);
addNode(head, 4100);
viewList(head); // I didn't upload here to save space
return 0;
}
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
void addNode(struct Node* head, int value)
{
if(head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = head;
head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = head;
head = newNode;
}
}
我感到困惑的原因是因为这个版本的添加节点不起作用,而这个版本确实......
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
并且在主函数中使用头节点指针
前面的安培数调用addNode(&head, 10);
令我感到困惑的是这个。我编写了一些练习函数,它们接受参数列表中的指针,并在函数内修改指针所指向的内容。我从来没有使用过这种**指针语法。
答案 0 :(得分:0)
这与参数按值传递有关。因此,在第一个非工作版本中,指向head
的指针按值传递,因此该变量是函数内的局部变量。当函数返回时,对函数外部的局部变量的更改不可见。
但是,在第二个版本中,您通过引用传递指针,因此该函数知道实际指针在内存中的位置,并且可以直接存储在该内存中。
ASCII图表时间:
假设您有以下三个变量:
int value1;
int *pointer1 = &value1;
int **pointer2 = &pointer1;
变量的内存如下所示:
+----------+ +----------+ +--------+ | pointer2 | --> | pointer1 | --> | value1 | +----------+ +----------+ +--------+
所以pointer2
指向pointer1
,pointer1
指向value1
。
使用*
上的解除引用运算符pointer2
将获得pointer2
指向的值,即pointer1
。
答案 1 :(得分:0)
文体(不要重复)::
void addNode(struct Node** head, int value)
{
if(*head == NULL)
{
struct Node *tmp = (struct Node *) malloc(sizeof(struct Node));
tmp->value = value;
tmp->next = *head;
*head = tmp;
}
else
{
struct Node *newNode = (struct Node *) malloc(sizeof(struct Node));
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
}
您不需要if / else ::
#include <stdlib.h>
void addNode(struct Node **head, int value)
{
struct Node *newNode = malloc(sizeof *newNode);
if ( !newNode) { error(); return;}
newNode->value = value;
newNode->next = *head; // Could be NULL, but we need a NULL anyway in that case
*head = newNode;
}
答案 2 :(得分:0)
这里效果不好
struct Node *createList()
{
struct Node *head = (struct Node *) malloc(sizeof(struct Node));
head = NULL;
return head;
}
分配节点并让头指向它后,设置为指向NULL。
答案 3 :(得分:0)
这是:
您有createList
struct Node *createList()
{
struct Node *head = malloc(sizeof(*head));
head->value = 0; //< Probably you want this
head->next = NULL; //< You definitively wanted this
return head;
}
如果要将节点添加到列表的尾部,则addNode
将如下所示:
void addNodeLast(struct Node* head, int value)
{
struct Node *tailNode;
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = NULL;
// Find the last node in the list
for (tailNode = head; tailNode->next; tailNode = tailNode->next);
tailNode->next = head->next;
}
如果在头部之后插入节点:
void addNodeAfterHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head-next;
head->next = newNode;
}
如果你正在改变头部(每次都要改头换面):
Node *addNodeNewHead(struct Node* head, int value)
{
struct Node *newNode;
newNode = malloc(sizeof(*newNode));
newNode->value = value;
newNode->next = head;
return newNode;
}
...
Node * head = createList();
head = addNodNewHead(head, 3);
head = addNodNewHead(head, 5);