假设我有以下结构:
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
(而不是双链表或循环列表,也称为环形缓冲区)。
请参阅下面的参考资料,了解有关单链表概念的更多信息。简而言之,你:
- 从列表中的第一个节点(
head
节点)开始 - 在列表中一次循环一个节点,将指针指向以前访问过的节点,直到找到要删除的节点
- 将列表中的上一个节点指向当前/找到的节点前面的节点
3.1.如果之后没有节点(我们在列表的末尾),则设置为NULL
3.2.如果找到的是头/第一个节点,则将head
节点设置为列表中的第二个节点 - 如果已找到节点,请删除该节点内的元素
- 删除当前节点本身
第二个参考对您非常有帮助,因为它涵盖了从头开始构建列表、将项目添加到列表末尾(追加)、在列表中的任意点插入项目、删除单个项目以及清除整个列表。
参考
-
从链表中删除,访问日期2014-04-22,
<https://www.cs.bu.edu/teaching/c/linked-list/delete/>
-
单链表-插入,删除,添加,计数源代码,访问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);
}