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

C语言基于谓词函数筛选链表元素构建新链表的实现问题

问题根因

你当前实现的split函数逻辑完全不符合筛选需求,存在以下核心错误:

  • 没有逐个筛选节点并添加到新链表,每次匹配到符合谓词的节点时,直接把当前节点之后的整段原链表整体赋值给新链表,直接覆盖新链表之前的所有内容
  • 直接篡改原链表的尾指针、节点指向、元素数量等元信息,彻底破坏了原链表的结构
  • 硬编码判断谓词返回值等于1,不符合你最初定义的「谓词返回非零即符合条件」的规则
  • 没有统计新链表的实际元素数量,直接复用原链表的数量值,元信息完全错误

基础依赖声明

首先明确你的链表结构通常的定义,以及默认已经实现的基础工具函数:

// 节点结构
typedef struct Noh {
  void *info;
  struct Noh *prox;
} Noh, *pNoh;

// 链表结构
typedef struct DLista {
  pNoh primeiro;
  pNoh ultimo;
  int quantidade;
} DLista, *pDLista;

// 基础工具函数,你已经实现无需额外编写
pDLista criarLista(); // 创建空链表
void adicionar(pDLista lista, void *info); // 向链表尾部追加元素

正确实现方案

根据你的需求不同,提供两种实现:

方案1:不修改原链表,复制符合条件的元素到新链表

适合只需要筛选结果、不需要改动原链表的场景:

pDLista split(pDLista pd, FuncaoPredicado fp) {
  pDLista pNovaListaComPredicado = criarLista();
  pNoh atual = pd->primeiro;

  while(atual != NULL) {
    // 谓词返回非零即符合条件,不要硬判等于1
    if(fp(atual->info)) {
      // 直接拷贝元素指针添加到新链表,如果是复杂结构可自行调整拷贝逻辑
      adicionar(pNovaListaComPredicado, atual->info);
    }
    atual = atual->prox;
  }

  return pNovaListaComPredicado;
}

方案2:拆分原链表,把符合条件的节点移到新链表

符合split函数的语义,执行后原链表仅保留不符合谓词的节点:

pDLista split(pDLista pd, FuncaoPredicado fp) {
  pDLista pNovaListaComPredicado = criarLista();
  pNoh atual = pd->primeiro;
  pNoh anterior = NULL;

  while(atual != NULL) {
    pNoh proximo = atual->prox;
    if(fp(atual->info)) {
      // 把当前节点从原链表摘除
      if(anterior == NULL) {
        pd->primeiro = proximo;
      } else {
        anterior->prox = proximo;
      }
      if(atual == pd->ultimo) {
        pd->ultimo = anterior;
      }
      pd->quantidade--;

      // 把当前节点挂载到新链表
      atual->prox = NULL;
      if(pNovaListaComPredicado->primeiro == NULL) {
        pNovaListaComPredicado->primeiro = atual;
        pNovaListaComPredicado->ultimo = atual;
      } else {
        pNovaListaComPredicado->ultimo->prox = atual;
        pNovaListaComPredicado->ultimo = atual;
      }
      pNovaListaComPredicado->quantidade++;
    } else {
      anterior = atual;
    }
    atual = proximo;
  }

  return pNovaListaComPredicado;
}

调用说明

你原来的调用逻辑不需要修改,针对原链表1-3-5-6-9,执行后新链表会返回3-6-9,完全符合筛选需求。注意你原来代码里的FuncaoImpressao pfi参数没有用到,可以直接删除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:54:03