Arrays 延迟删除对二叉树或链表有什么好处/坏处?

Arrays 延迟删除对二叉树或链表有什么好处/坏处?,arrays,linked-list,binary-tree,Arrays,Linked List,Binary Tree,最近,对于一个数据结构类,有人问我一个问题:延迟删除(即,首先标记需要删除的项,然后在某个时间删除所有标记的项的删除)对数组、链表或二叉树如何有利/不利。以下是我的想法: 这将有助于数组,因为您可以节省每次删除索引时移动数组所需的时间,尽管在需要遍历数组的算法中,可能存在效率低下的问题 这对链表没有帮助,因为您需要遍历O(n)来标记要删除的项目 我不完全确定二叉树,但如果它是一个二叉树的链表实现,我会想象它就像链表一样 也许您需要对链表的实现进行更深入的思考。您指出延迟删除在任何方面都没有帮助

最近,对于一个数据结构类,有人问我一个问题:延迟删除(即,首先标记需要删除的项,然后在某个时间删除所有标记的项的删除)对数组、链表或二叉树如何有利/不利。以下是我的想法:

  • 这将有助于数组,因为您可以节省每次删除索引时移动数组所需的时间,尽管在需要遍历数组的算法中,可能存在效率低下的问题
  • 这对链表没有帮助,因为您需要遍历O(n)来标记要删除的项目
  • 我不完全确定二叉树,但如果它是一个二叉树的链表实现,我会想象它就像链表一样

也许您需要对链表的实现进行更深入的思考。您指出延迟删除在任何方面都没有帮助,因为搜索时间是执行删除所需的全部时间

想想从链表中实际删除一个项目需要什么。 注意:这假定为单链接列表(不是双链接列表) 1) 查找要删除的项目(因为这是一个单链表,所以您必须始终进行搜索,因为您需要上一个项目) 2) 保留指向上一个和下一个元素的指针 3) 固定“PREV”元素以指向下一个元素-从而隔离当前元素 3.5)在双链接列表中,您还必须注意指向上一个元素的下一个元素。 4) 释放与当前元素关联的内存

现在,延迟删除的过程是什么?--短得多 1) 查找要删除的项目(您甚至可能不必执行搜索,因为您已经有了指向要删除的对象的指针?) 2) 标记要删除的项目

*)等待“垃圾收集”线程运行,并在系统“空闲”时实际执行其余步骤

实现为链表的二叉树,其中每个元素都有一个左和一个右-但是,在搜索中仍然执行相同的步骤。我相信使用O(Log(n))二叉树搜索更有效


但是,由于要处理更多的指针(“左”和“右”),因此从这些节点中删除变得更加复杂-因此需要更多的指令来修复,特别是当您删除一个树节点时,该树节点具有指向左和右节点的指针-其中一个需要升级到新根-但是,如果它们也都已经分配了左指针和右指针呢?原来的“左/右”节点在哪里此时必须重新平衡树。因此,从用户的角度来看,标记删除和使用“空闲”垃圾收集来处理内存详细信息(这样用户就不必等待内存详细信息)可以大大节省成本。

我认为答案可能是“这取决于”各种原因,但我认为您的思路是正确的

1) 我同意你关于阵列的回答,假设你的阵列中没有洞。如果您不需要在每次删除时移动数组,那么建议的“现在标记,以后删除”方法将毫无帮助。无论哪种方式,您都要处理算法的O(n)vs.(2O(n)=O(n)),它们是相等的。真正需要考虑的是“一次对所有删除进行重新排序与对每个删除进行单独重新排序相比,是否节省了您的时间?”假设m是删除的数量,数组中第一次删除后的每个元素重新排序的次数是O(m),与O(1)相比,对于删除立即接近对于现在的标记,请删除以后的方法

2) 我同意你对链表的回答


3) 至于二叉树,我想这取决于它是什么类型的。如果你使用的是排序的平衡二叉树,你必须考虑与上面1中相同的问题,但是如果不是,你的想法是正确的,并且它应该表现得像一个链表。

< P>我认为这完全取决于环境和需求。在一般意义上,使用这种方法,它们被标记,然后被删除,它们都有许多相似的优点和缺点

类似的优点: -当标记为删除时,数据结构不会移动,这使得删除速度更快。 -您可以在已删除项的顶部插入,这意味着插入也不会移动,而且插入可以更快,因为它可以在第一次删除时写入,而不是查找列表的结尾

类似的缺点: -删除的项目浪费空间,因为他们只是坐在那里 -删除一个项目需要两次,一次标记,一次删除 -许多标记要删除的项目将污染数据结构,这使得搜索需要更长的时间,因为必须对已删除的项目进行搜索