c-结构-删除其中一个元素



假设我有以下结构:

struct object {
    char *name;
    struct object *next;
};

使用它,我可以很容易地创建一个如K&R C书。并通过以下方式删除所有对象:

object *object_destroy(object *obj)
{
    if (obj != NULL) {
        object_destroy(obj->next);
        free(obj->name);
        free(obj);
        obj = NULL;
    }
}

但我想要的是删除表中的一个对象,保存所有其他。我真的不知道如何实现,因为仅仅free()对象是不起作用的:之后的对象将永久丢失。接下来我也不能obj_to_remove=obj_to_remove->,因为在那之后,我将丢失该对象之前的所有对象。

你能告诉我我缺了什么吗?谢谢

您实际上是在试图从单链表中删除单个node(而不是双链表或循环列表,也称为环形缓冲区)。

请参阅下面的参考资料,了解有关单链表概念的更多信息。简而言之,你:

  1. 从列表中的第一个节点(head节点)开始
  2. 在列表中一次循环一个节点,将指针指向以前访问过的节点,直到找到要删除的节点
  3. 将列表中的上一个节点指向当前/找到的节点前面的节点
    3.1.如果之后没有节点(我们在列表的末尾),则设置为NULL
    3.2.如果找到的是头/第一个节点,则将head节点设置为列表中的第二个节点
  4. 如果已找到节点,请删除该节点内的元素
  5. 删除当前节点本身

第二个参考对您非常有帮助,因为它涵盖了从头开始构建列表、将项目添加到列表末尾(追加)、在列表中的任意点插入项目、删除单个项目以及清除整个列表。

参考


  1. 从链表中删除,访问日期2014-04-22,<https://www.cs.bu.edu/teaching/c/linked-list/delete/>
  2. 单链表-插入,删除,添加,计数源代码,访问2014-04-22,<http://www.cprogramming.com/snippets/source-code/singly-linked-list-insert-remove-add-count>

您有以下1->2->3->4->5,并且您想要移除元素3。最终结果将是1->2->4->5。

要做到这一点,您只需要执行以下步骤:

1-如果元素位于列表的中间:

  • 遍历表,为每个元素保存上一个元素和元素本身。

  • 当元素等于要删除的元素时,cur_el=3,prev_el=2。(cur_el和prev_el是指向元素3和2的指针)

  • 现在只需使prev_el->next=cur_el->next(不要忘记保留一个指向prev_el.的指针

  • 终于放开cur_el了。

2-如果元素是列表中的第一个(假设你想删除1):-将第一个列表元素设置为cur_el->next(此处cur_el指向1,列表中的第一个元素)

  • 释放cur_el

3-如果元素在列表的末尾(在本例中为5):-转到最后一个元素,获得倒数第二个元素(让我们调用指向这个元素的指针prev_el)

  • 设置prev_el->next=null

  • 免费cur_el

此外,请注意,从列表中删除元素的复杂性为O(n),其中n是列表中元素的数量。如果你只是从开始或结束插入和移除,你可以达到O(1)。

在问题中,内存结构被称为"表"。也许把它称为"链表"会更好。

int object_destroy(
      object **head, /* The head of the linked-list is required in order to maintain proper list nodes linkage. */
      object  *obj
      )
   {
   int rCode=0;
   /* Unlink the node to be destroyed. */
   if(*head == obj)  /* Is the obj to destroy the head list node? */
      *head = obj->next;
   else 
      {
      object *temp = *head;
      /* Find the parent list node (to the one that will be destroyed). */
      while(temp)
         {
         if(temp->next == obj)
            break;
         temp=temp->next;
         }          
      /* Not found? */
      if(NULL == temp)
         {
         rCode=ENOENT;
         fprintf(stderr, "obj node not found in listn");
         goto CLEANUP;
         }
      /* Unlink the node, and patch the list so that remaining nodes are not lost. */
      temp->next = temp->next->next;
      }
   /* Free the node to be destroyed. */
   if(obj->name)
      free(obj->name);
   free(obj);
CLEANUP:
   return(rCode);
   }

相关内容

最新更新