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

使用单链表查找指定节点并移至表头时遇空指针解引用错误

单链表指定位置节点移至头部的空指针问题解决

现有代码的核心问题

  • 缺参数合法性校验:
    1. 链表为空时,size是0,后续直接访问cur->word必然触发空指针解引用。
    2. 当index小于1或者大于链表实际长度时,size - index会出现负数或超出范围,循环逻辑乱掉,最后大概率让cur指向NULL再访问成员,直接出错。
  • 节点定位逻辑完全错误:
    你用的是头插法加节点,链表顺序和添加顺序反过来(最后加的在头部,第一个加的在尾部)。现在代码里while (i < (size - index))的计算逻辑完全不对,比如要找第1个节点(头部),算出来的size - index是size-1,循环会让cur走到倒数第二个节点,根本不是目标。
  • 没做节点移动的核心操作:目前只尝试打印,还没实现移到头部的逻辑。

修正后的完整实现

下面是补全逻辑、修复空指针问题的代码,包含节点移动的完整功能:

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

#define WORDSIZE 64

typedef struct node NODE;
struct node
{
    char word[WORDSIZE];    
    struct node* next;      
};

NODE* start;

int add_to_list(NODE** start, char data[])
{
    NODE* new_node = malloc(sizeof(NODE));
    if (new_node == NULL)
        return -1;

    strcpy_s(new_node->word, WORDSIZE, data);
    new_node->next = *start;
    *start = new_node;

    return 0;
} 

// 查找指定位置节点并移至头部,返回0成功,-1失败
int FindMoveToHead(NODE** start, int index) {
    if (*start == NULL || index < 1) {
        // 链表为空或索引非法
        return -1;
    }

    // 先算链表长度,同时校验索引是否超出范围
    int size = 0;
    NODE* cur = *start;
    while (cur != NULL) {
        size++;
        cur = cur->next;
    }
    if (index > size) {
        // 索引超过链表实际长度
        return -1;
    }

    // 目标已经是头部,不用动
    if (index == 1) {
        printf("目标节点已在头部:%s\n", (*start)->word);
        return 0;
    }

    // 找到目标节点的前驱节点
    NODE* prev = *start;
    // 要找第index个节点,前驱是第index-1个,所以循环index-2次
    for (int i = 1; i < index - 1; i++) {
        prev = prev->next;
    }
    NODE* target = prev->next;

    // 把目标节点从原位置摘出来
    prev->next = target->next;

    // 把目标节点插到头部
    target->next = *start;
    *start = target;

    printf("已移动节点至头部:%s\n", target->word);
    return 0;
}

// 测试示例
int main() {
    add_to_list(&start, "first");
    add_to_list(&start, "second");
    add_to_list(&start, "third");

    // 打印原链表
    printf("原链表:");
    NODE* cur = start;
    while (cur != NULL) {
        printf("%s ", cur->word);
        cur = cur->next;
    }
    printf("\n");

    // 移动第3个节点(原first)到头部
    FindMoveToHead(&start, 3);

    // 打印移动后的链表
    printf("移动后链表:");
    cur = start;
    while (cur != NULL) {
        printf("%s ", cur->word);
        cur = cur->next;
    }
    printf("\n");

    return 0;
}

关键修正点说明

  • 加了严格的参数校验:先判断链表空、索引是否在1到链表长度之间,从源头避免空指针访问。
  • 修正了节点定位逻辑:根据头插法的链表特性,准确找到目标节点的前驱,不会再定位错误。
  • 完整实现移动逻辑:先把目标节点从原位置断开,再插到头部,同时用NODE**参数确保头部指针的修改能同步到外部。
  • 处理了特殊情况:如果目标已经是头部,直接返回,避免做无用操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:10:37