void add(llist *list, lnode *newNode){
list->size++;
addRecursion(&list->head, newNode);
}
lnode* addRecursion(lnode **node, lnode *newNode){
if(*node == NULL){
*node = newNode;
}
else{
lnode *nextNode = (*node)->next;
(*node)->next = addRecursion(&nextNode, newNode);
}
return *node;
}
此代码工作正常..我在网上查看了代码并进行了一些更改。但我仍然不明白为什么addRecursion函数必须具有返回类型。我改变了像
这样的功能void addRecursion(lnode **node, lnode *newNode){
if(*node == NULL){
*node = newNode;
}
else{
lnode *nextNode = (*node)->next;
addRecursion(&nextNode, newNode);
}
}
然后它没有用..
答案 0 :(得分:2)
它始终将它存储的值返回到* node,并且在修改后的代码中它会丢失该值,因为递归调用传递的是本地临时值,而不是它实际需要放置值的位置,然后在它之后执行存储回报。一个非常奇怪的结构。如果你只是去掉那个局部的var:
,你可以使addRecursion变为void(和更简单)void addRecursion(lnode **node, lnode *newNode){
if(*node == NULL){
*node = newNode;
}else{
addRecursion(&(*node)->next, newNode);
}
}
答案 1 :(得分:1)
为(*node)->next
分配内容。我想,这指向列表的下一个节点。因此,如果没有该分配,列表将不会转到要添加新节点的最后一个节点。递归可以用迭代替换。
答案 2 :(得分:1)
因为函数返回算法中设置最终节点所需的下一个节点的地址。
答案 3 :(得分:1)
随着递归的进行,可视化调用堆栈的增长/收缩可能会有所帮助。假设以下列表:
node1 -> node2 -> node3 -> null
然后addRecursion
展开如下(伪代码):
addRecursion(&node1, newNode)
node1.next = addRecursion(&node2, newNode);
node2.next = addRecursion(&node3, newNode);
node3.next = addRecursion(null, newNode); // returns &newNode
node3.next = &newNode;
node2.next = &node3;
node1.next = &node2;
// return value ignored
新节点被添加到结尾,链中的每个链接都会被保留。
答案 4 :(得分:0)
如果您对代码进行此调整,并将nextNode
的值重新分配回(*node)->next
,因为您通过引用递归函数调用传递了该值,因此它也应该有效(因此它在以后的递归调用中被修改了:
void addRecursion(lnode **node, lnode *newNode)
{
if(*node == NULL)
{
*node = newNode;
return;
}
lnode *nextNode = (*node)->next;
addRecursion(&nextNode, newNode);
(*node)->next = nextNode; //Add this line to re-connect the link
}
上面的Chris版本有点干净,因为它会分出两个分配,这样做也可以节省一些空间,因为本地指针变量nextNode
不需要存储空间。