You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归双向链表反转函数异常终止问题排查及传参正确性咨询

双向链表递归反转问题排查

问题背景

编写递归函数实现双向链表反转,代码未完成,程序执行中途退出,相关代码、运行输出及疑问如下:

代码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct nodes
{
    uint8_t x;
    struct nodes *next;
    struct nodes *prev;
}Node;

Node *head = NULL;

void rev_rec_dll(Node **a, Node **b)
{
        //check if it is last node in the list
    if((*a)->next != NULL)
    {
                //set next to prev and prev to next
        (*a)->next = (*a)->prev;
        (*a)->prev = (*b);
        printf("done for node %d and moving on..\n", ((*a)->x));
        //recursive call by passing next two nodes
                rev_rec_dll(b, &((*b)->next));
    }
    else
    {
        printf("reached new head\r\n");
        head = (*a);
    }
}

void add_node(Node **h_node, uint8_t x)
{
        //check if there is at least one node in the list and if not add first node
    if((*h_node) == NULL)
    {
        *h_node = (Node *)malloc(sizeof(Node));
        (*h_node)->x    = x;
        (*h_node)->next = NULL;
        (*h_node)->prev = NULL;
    }
    else
    {
        Node *temp = *h_node;
        //get the last node
        while(temp->next != NULL)
        {
            temp = temp->next;
        }
        //add new node
        Node *newNode = (Node *)malloc(sizeof(Node));
        
        newNode->x      = x;
        newNode->next   = NULL;
        newNode->prev   = temp;
        
        temp->next      = newNode;
    }
}

void display_nodes(Node *h_node)
{
    while(h_node != NULL)
    {
        printf("Node: %u\n", h_node->x);
        h_node = h_node->next;
    }
}

int main(int argc, char **argv)
{
        //add three nodes
    add_node(&head, 1);
    add_node(&head, 2);
    add_node(&head, 3);

    //display nodes
    display_nodes(head);

        //add three more nodes
    add_node(&head, 4);
    add_node(&head, 5);
    add_node(&head, 6);

        //display all 6 nodes
    display_nodes(head);
    
        //reverse the linked list
    rev_rec_dll(&head, &(head->next));

        //display reversed nodes 
    display_nodes(head);
    
    return 0;
}

运行输出

Node: 1
Node: 2
Node: 3
Node: 1
Node: 2
Node: 3
Node: 4
Node: 5
Node: 6
done for node 1 and moving on..

疑问解答

1. rev_rec_dll()函数存在的问题

  • 递归逻辑混乱:修改当前节点指针后,后续递归的参数引用的是已被修改的指针,导致节点跟踪错误;最后一个节点的指针反转未完成,也没有处理新头节点与后续节点的链接。
  • 边界处理缺失:未判断输入指针是否为空,若链表为空或只有一个节点,会直接触发空指针解引用;递归终止时仅设置新头节点,未完成整个链表的闭环调整。
  • 指针修改顺序错误:先修改当前节点的next指针,导致后续无法正确获取原本的下一个节点,破坏了递归的节点链跟踪。

2. 传入函数的参数是否正确

不正确。
原因:第一次调用传入的&head和&(head->next),在函数内部修改(*a)->next为(*a)->prev(即NULL)后,后续递归传入的&((*b)->next)会随着节点指针的修改指向错误地址。参数设计逻辑错误,应该传递当前节点的原始下一个节点引用,而非动态变化的指针地址,否则会导致递归过程中节点链断裂,访问非法内存。

3. 程序中途退出的原因

是内存违规(空指针解引用或非法内存访问)导致的。
具体来说:递归过程中,当处理到某个节点时,(*b)可能变为NULL(比如链表末尾的下一个节点),此时解引用(*b)->next会触发空指针异常;另外,节点指针被错误修改后,后续递归访问的内存地址已失效,触发内存访问违规,导致程序直接崩溃退出。


内容的提问来源于stack exchange,提问作者Karna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:20:47