链接列表递归..为什么我需要return语句?

时间:2011-03-24 23:39:10

标签: c recursion linked-list

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);

        }
    }

然后它没有用..

5 个答案:

答案 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不需要存储空间。