递归 - 链表中最后一个元素

时间:2015-06-09 00:32:27

标签: c recursion linked-list

有人可以解释以下功能吗?

void printNthFromLast(struct node* head, int n) 
{
    static int i = 0;
    if(head == NULL)
       return;
    printNthFromLast(head->next, n);
    if(++i == n)
       printf("%d", head->data);
}

我只是想知道在递归中如何执行语句的顺序,即如果递归调用在第二个if条件之前,那么第二个if条件是否会被检查?

2 个答案:

答案 0 :(得分:1)

  

我只是想知道在递归中如何执行语句的顺序,即如果递归调用在第二个if条件之前,那么第二个if条件是否会被检查?

是的,在递归调用返回后,将检查第二个if条件。如果递归到达链表的末尾,它将返回。这个概念对于理解递归至关重要。最重要的是,您必须了解每个函数调用(包括递归调用)都在其自己的上下文中执行,并且在调用之后立即恢复控制。它与执行流程相关联,而不是与被调用的函数相关联 - 您不会通过递归调用函数来丢失位置。

答案 1 :(得分:0)

函数printNthFromLast以递归方式为链表中的每个节点调用自身。返回时,i递增,并且仅为递归的data返回打印字段n,因此对于列表末尾的n项,最后一次计为1printNthFromEnd将是一个更准确的名称。

此功能仅作为测验有趣:它更新全局不可访问状态,因此只能正常工作一次!它是非可重入行为的缩影:不仅不应该在不同的线程中使用它,它不应该被多次使用,周期。可以将此方法扩展为通过另一个static变量从末尾获取第n个模式:

void getNthFromEnd(struct node *head, int n) {
    static int i = 0;
    static struct node *np = NULL;
    if (head != NULL) {
        getNthFromEnd(head->next, n);
        if (++i == n) np = head;
    }
    return np;
}

更好的选择是:

struct node *getNthFromEnd(struct node *head, int n) {
    struct node *np;

    for (np = head; n > 0; n--) {
        if (np == NULL) return NULL;
        np = np->next;
    }
    while (np != NULL) {
        head = head->next;
        np = np->next;
   }
    return head;
}