删除链接列表中的最后一个节点

时间:2014-05-22 22:05:30

标签: c linked-list

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

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);
}

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

它没有运行,如果你能提供帮助,我将不胜感激。

谢谢, 拉杜

4 个答案:

答案 0 :(得分:3)

你的p永远不会被初始化,因此它指向内存中的随机地址,然后你访问它会导致未定义的行为。

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

答案 1 :(得分: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;
}

答案 2 :(得分:2)

我会像这样实现它:

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

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

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

sterge_ultimul(&lista);

如果列表只包含一个元素,则删除最后一个元素,并在调用后lista0

答案 3 :(得分:1)

您没有初始化 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);
}

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