大家好,我是 C 语言的新手,正在努力学习它。我对这个链接列表实现有一个简单的查询,我在很多地方都找到了:
void addNode(node **listhead, int data, int pos){
if(pos<=0 || pos > length(*listhead)+1){
printf("Invalid position provided, there are currently %d nodes in the list n", length(*listhead));
return;
}else{
node *current = *listhead;
node *newNode = (node*)malloc(sizeof(node));
if(newNode == NULL){
printf("Memory allocation errorn");
return;
}
newNode->data = data;
newNode->next = NULL;
if (current == NULL){
*listhead = newNode;
return;
}else{
int i = 0;
while(current->next != NULL && i < pos-1){
++i;
current = current->next;
}
if(current->next == NULL){
current->next = newNode;
}
if(i == pos-1){
newNode->next = current->next;
current->next = newNode;
}
}
}
}
int main(){
node *head = NULL;
node **headref = &head;
addNode(headref, 1, 1);
addNode(headref, 2, 2);
addNode(headref, 3, 3);
printList(head);
return 0;
}
我的查询是在这里,我们正在创建一个指向 NULL 的指针的指针。这段代码有效,但我想知道这是否是一种好的做法。如果不是,我应该如何创建我的头指针并将其引用传递给 addNode 函数。
建议的替代方案:
int main() {
node *head = addNode(NULL, 1, 1);
node *current = head;
current = addNode(current, 2, 2);
current = addNode(current, 3, 3);
printList(head);
return 0;
}
换句话说:
1) addNode() 成为一个将当前值作为参数的函数(因此它不必为了添加新元素而遍历整个列表)...
2) ...并返回指向新节点的指针。
3)这意味着在程序的任何一点,您都可以访问a)列表头,b)上一个指针(在"添加"之前)和/或c)下一个指针(在添加之后)中的任何一个。
对于需要更新 headref 指针的情况,我们将双指针传递给 addNode()。对于这种情况,使用 "addNode(headref, 1, 1);",addNode 很可能将错误定位元素的地址存储在 headref 中的 addNode() 中。如果你要传递 headref 作为指针,那么在调用之后,headref 将继续指向 main 中的地址,你将丢失错误定位的地址。
对于单个链表,这实际上是一个很好的做法,它简化了addNode的实现。我想对addNode(node_x, 1, 1)
的调用会在node_x
之前添加一个节点。如果仅将指针传递给 node_x
.然后,该函数将需要遍历整个列表并在node_x
之前找到节点,并修改其指向新构造节点的指针。而如果你传递一个指向指针的指针,假设node** p
那么该函数只需要将新节点的地址分配给*p
。