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

C语言双向链表删除唯一元素的代码修复求助

问题排查与修复方案

核心问题分析

你遇到的内循环结束后后续代码未执行、删除逻辑失效的问题,大概率是因为嵌套循环导致指针混乱或删除节点时未正确维护链表指针,常见场景包括:

  • 内循环遍历统计次数后,未重置遍历指针,导致后续循环直接终止;
  • 删除节点时未提前保存下一个节点的地址,导致遍历链断裂;
  • 处理头节点删除时未更新链表头指针,造成链表丢失。

修复后的完整代码

假设你的双向链表节点结构定义如下:

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

typedef struct Node {
    char data;
    struct Node* prev;
    struct Node* next;
} Node;

// 创建新节点
Node* create_node(char data) {
    Node* new_node = (Node*)malloc(sizeof(Node));
    new_node->data = data;
    new_node->prev = NULL;
    new_node->next = NULL;
    return new_node;
}

// 打印链表
void print_dll(Node* head) {
    Node* current = head;
    while (current != NULL) {
        printf("%c", current->data);
        if (current->next != NULL) {
            printf("<->");
        }
        current = current->next;
    }
    printf("<->NULL\n");
}

修复后的remove_unique_dll函数:

void remove_unique_dll(Node** head) {
    if (*head == NULL) return;

    // 第一步:一次性统计所有字符的出现次数
    int count[256] = {0};
    Node* current = *head;
    while (current != NULL) {
        count[(unsigned char)current->data]++;
        current = current->next;
    }

    // 第二步:遍历链表,删除出现次数为1的节点
    current = *head;
    while (current != NULL) {
        // 提前保存下一个节点,防止删除当前节点后遍历链断裂
        Node* next_node = current->next;

        if (count[(unsigned char)current->data] == 1) {
            // 处理头节点删除
            if (current->prev == NULL) {
                *head = next_node;
                if (next_node != NULL) {
                    next_node->prev = NULL;
                }
            } 
            // 处理中间/尾节点删除
            else {
                current->prev->next = next_node;
                if (next_node != NULL) {
                    next_node->prev = current->prev;
                }
            }
            free(current);
        }
        // 用提前保存的节点继续遍历
        current = next_node;
    }
}

关键修复点说明

  1. 分离统计与删除逻辑:
    先一次性遍历链表统计所有字符的出现次数,避免嵌套循环导致的指针混乱——原嵌套循环可能在统计时修改了遍历指针,导致后续代码无法执行。
  2. 提前保存下一个节点:
    删除当前节点前先保存next_node,防止删除后无法继续遍历链表(如果直接用current = current->next,删除current后会访问空指针)。
  3. 正确维护头节点:
    当删除的是头节点时,必须更新*head指针,否则会导致链表头丢失,后续操作无意义。
  4. 空指针检查:
    所有指针操作前都检查是否为NULL,避免访问空指针导致程序崩溃。

验证示例

输入链表a->a->c->b(对应输入字符串aacb),执行修复后的函数后:

  • 统计得到count['a']=2,count['c']=1,count['b']=1;
  • 遍历删除c和b节点,最终输出a<->a<->NULL,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:50:22