您能想到任何特定的原因,为什么对于许多(大多数)数据结构而言,删除通常比插入要难得多吗?
快速示例:链接列表。插入是微不足道的,但是删除有一些特殊情况,使插入变得非常困难。自平衡二进制搜索树(例如AVL和Red-black)是痛苦的删除实现的经典示例。
我想说这与大多数人的想法有关:对于我们而言,以结构性方式定义事物更容易,这很容易导致插入。
您能想到任何特定的原因,为什么对于许多(大多数)数据结构而言,删除通常比插入要难得多吗?
快速示例:链接列表。插入是微不足道的,但是删除有一些特殊情况,使插入变得非常困难。自平衡二进制搜索树(例如AVL和Red-black)是痛苦的删除实现的经典示例。
我想说这与大多数人的想法有关:对于我们而言,以结构性方式定义事物更容易,这很容易导致插入。
Answers:
这不只是一种心境。有一些物理(即数字)原因导致删除操作更加困难。
删除时,您会在以前的位置留下一个漏洞。所得熵的技术术语是“碎片”。在链接列表中,这要求您“修补”已删除的节点并重新分配它正在使用的内存。在二叉树中,它导致树的不平衡。在内存系统中,如果新分配的块大于删除所留下的块,则会导致内存暂时闲置。
简而言之,插入比较容易,因为您可以选择要插入的位置。删除起来比较困难,因为您无法提前预测将要删除的项目。
为什么它往往比插入难于删除?数据结构在设计时更着眼于插入,而不是删除。
考虑这一点-为了从数据结构中删除某些内容,它必须首先存在。因此,您需要先添加它,这意味着最多可以有和插入一样多的删除。如果优化用于插入的数据结构,则可以确保获得的收益至少与针对删除进行了优化一样。
此外,按顺序删除每个元素有什么用?为什么不立即调用某个将其全部清除的函数(可能只是通过创建一个新函数)呢?同样,当数据结构实际包含某些内容时,它们也是最有用的。因此,实际上,删除与插入一样多的情况并不常见。
当您优化某件事时,您想优化其最常做且花费最多时间的事情。在正常使用中,数据结构元素的删除发生的频率要小于插入操作。
k
非常快速地添加一批元素:反向排序输入并与现有向量-合并O(k log k + n)
。然后,您将获得一个结构,其中的插入操作相当复杂,但是消耗顶级u
元素却是微不足道且快速的。只需最后u
移动向量的结尾即可。但是,如果有人需要这样的东西,我该死的。我希望这至少可以加强您的论点。
这并不难。
使用双向链表,在插入时,您将分配内存,然后将与头节点或前一个节点以及尾节点或下一个节点进行链接。删除时,您将取消完全相同的链接,然后释放内存。所有这些操作都是对称的。
假定在两种情况下都具有要插入/删除的节点。(在插入的情况下,您也要在之前插入节点,因此,从某种意义上说,插入可能会稍微复杂一些。)如果您要删除而没有删除的节点,而是要删除的负载节点,那么您当然必须首先在列表中搜索有效载荷,但这并不是删除的缺点,不是吗?
对于平衡树,这同样适用:一棵树通常需要在插入后立即删除,也需要在删除后立即保持平衡。尝试仅拥有一个平衡例程,并在每次操作之后应用它是一个好主意,而不管它是插入还是删除。如果您尝试实现始终使树保持平衡的插入操作,以及试图使树始终保持平衡的删除操作,而又没有使两者共享相同的平衡例程,那么不必要地会使您的生活变得复杂。
简而言之,没有理由为什么一个人应该比另一个人更难,而且如果您发现确实如此,那么实际上您很有可能是(非常人性化的)趋势的受害者建设性的而不是消减的,这意味着您可能以比所需复杂的方式实现删除。但这是人类的问题。从数学的角度来看,没有问题。
在运行时方面,在Wikipedia上查看数据结构操作时间复杂度的比较,请注意插入和删除操作具有相同的复杂度。那里描述的删除操作是按索引删除的,您可以在其中引用要删除的结构元素。插入是按项目进行的。实际上,删除的运行时间较长是因为您通常要删除一个项目而不是其索引,因此还需要执行查找操作。该表中的大多数数据结构都不需要为插入内容额外查找,因为放置位置不依赖于项,或者该位置是在插入过程中隐式确定的。
至于认知的复杂性,这个问题有一个答案:边缘案例。删除中可能包含的内容比插入要多(一般情况下尚未确定)。然而,在某些设计中可以避免这些边缘情况中的至少一些(例如,在链表中具有前哨节点)。
最重要的是涉及数据引用完整性。对于SQL中最合适的数据结构(如SQL中的数据库),Oracle参照完整性非常重要。
为确保您不会意外破坏它而发明了许多不同的东西。
例如,在删除时级联,它不仅删除您尝试删除的内容,还会触发相关数据的清除。
这样可以清除垃圾数据中的数据库,并保持数据完整性。
例如,在第二个表中,您有具有父项和种类的表作为相关记录。
父母是主表。如果没有适当的参照完整性,则可以删除任何表中的任何记录,以后再也不知道如何获取完整的家庭信息,因为子表中有数据,而父表中没有任何数据。
这就是为什么引用完整性检查将不允许您清除父表中的记录,直到清除子表中的记录。
这就是为什么在大多数数据源中删除数据更加困难。
pop
,extract-min
?