【问题标题】:Delete the last node in a linked list删除链表中的最后一个节点
【发布时间】:2014-05-22 22:05:29
【问题描述】:

我正在尝试删除链表中的最后一个节点,但我似乎遇到了一些困难。 这是代码。

void sterge_ultimul(element *lista) {
  element *p,*q;
  while (p->urmator->urmator!=NULL)
    p=p->urmator;
  q=p->urmator;
  p->urmator=NULL;
  free(q);
}

英语:

void delete_last(element *list) {
   component *p, *q;
   while (p->next->next != NULL)
     p = p->next;
   q = p->next;
   p->next = NULL;
   free(q);
}

我已经完成了删除列表头部的功能,所以我认为我不需要担心。

它无法运行,如果您能提供帮助,我将不胜感激。

谢谢, 拉度

【问题讨论】:

  • 您考虑过自己调试它,而不是把“它不运行”强加给其他人,希望一些代表百吉饼发布解决方案?
  • 这个问题似乎是题外话,因为它是关于太空闲而根本无法进行任何调试,宁愿多个 SO 贡献者都经历同样的事情。

标签: c linked-list


【解决方案1】:

您的 p 从未初始化,因此它指向内存中的一个随机地址,然后您访问它会导致未定义的行为。

你想要的是用列表的第一个元素(lista)初始化 p。然后,您需要考虑您的逻辑,特别是如果您在只有一个节点的情况下尝试删除链表的最后一个节点会发生什么。

【讨论】:

  • 感谢您的回复。当只有一个节点时,我的函数中有一个部分来处理它。
  • @Matei_Radu:好的,那么经过初始化的代码应该可以工作了。
【解决方案2】:

初始化p:

void sterge_ultimul(element *lista) {
  element *p = lista, *q;
  while (p->urmator->urmator!=NULL)
    p=p->urmator;
  q=p->urmator;
  p->urmator=NULL;
  free(q);
}

我还会添加一些错误处理来检查列表是否太短:

int sterge_ultimul(element *lista) {
  element *p = lista, *q;
  if (!p || !p->urmator) return 0;  /* error, list is too short */
  while (p->urmator->urmator!=NULL)
    p=p->urmator;
  q=p->urmator;
  p->urmator=NULL;
  free(q);
  return 1;
}

【讨论】:

  • OP 在评论中说他有其他代码来处理列表只有一个元素的情况。所以在这里只返回而不删除它就可以了。
  • 如果只包含一个元素,函数不应该删除头部吗? (编辑)对,第二个 sn-p 进行检查。第一个访问p->urmator->urmator 而不首先检查p->urmator。
【解决方案3】:

我会这样实现它:

void sterge_ultimul(element** p)
{        
    while(*p && (*p)->urmator)
        p = &(*p)->urmator;

    free(*p);
    *p = 0;
}

使用此版本,当列表中只有一个元素时,您还可以删除最后一个元素。应该使用指向列表的指针的地址来调用它:

sterge_ultimul(&lista);

如果列表只包含一个元素,则删除最后一个元素,调用后lista将变为0。

【讨论】:

  • 最后一个元素之前的元素在删除尾部后也应该将其p->urmator设置为NULL。
  • @Groo 这是通过最后一行 *p = 0 完成的。 p 指向最后一个元素的指针,如果只有一个元素指向 lista,如果元素很多,指向 x->uramator。
  • 哦对,整个函数都是element**,我的错。 +1
【解决方案4】:

你没有初始化 p 指针。它的值是不确定的。

读取未初始化的对象是未定义的行为。未定义的行为意味着任何事情都可能发生。任何事情都包括你的程序很可能崩溃。

对于 C90,请参阅未定义行为定义中的 3.16,对于 C11,请参阅 6.3.2.1p2,对于 C99,请参阅 DR#338. 中的 C 委员会答复

C90

未定义的行为:使用时的行为 [...] 或不确定值的对象 [...]

(C11, 6.3.2.1p2)

"如果左值指定了一个可以使用寄存器存储类声明的具有自动存储持续时间的对象(从未使用过它的地址),并且该对象未初始化(未使用初始化程序声明并且没有分配给它已在使用前执行),行为未定义。”

以下是正确的函数:

void sterge_ultimul(element *lista) 
{
  element *p = lista , *q;
  while (p->urmator->urmator!=NULL)
    p=p->urmator;
  q=p->urmator;
  p->urmator=NULL;
  free(q);
}

英语

void delete_last(element *list) 
{
  component *p = list, *q;
  while (p->next->next != NULL)
    p = p->next;
  q = p->next;
  p->next = NULL;
  free(q);
}

一般建议:当您在代码中看到未初始化的指针(或一般的变量和对象)时,请始终确保您有充分的理由。这个小检查将为您以后调试代码省去很多麻烦。

【讨论】:

    猜你喜欢
    • 2016-06-11
    • 2013-03-25
    • 2014-05-22
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多