Data structures O(1)删除操作

Data structures O(1)删除操作,data-structures,time-complexity,Data Structures,Time Complexity,是否有任何数据结构或现有数据结构的变体为删除操作提供O(1)或恒定时间复杂性 我知道哈希表可以做到这一点。但我正在修改哈希表,在这里,我们可以在不经过所有存储桶的情况下获得所有的键,为了做到这一点,我将每个键存储在另一个链表中,并在我将其添加到哈希表时存储。这样我就能很快把所有的钥匙都拿进去 当然有,但有所有警告之母 一个简单的节点数组,其中已删除的节点具有deleted标志,具有恒定的删除时间,但这是一个警告,它对所有其他操作的时间要求极为苛刻 编辑 答案最初提到的是排序数组,但这是错误的单词

是否有任何数据结构或现有数据结构的变体为删除操作提供O(1)或恒定时间复杂性


我知道哈希表可以做到这一点。但我正在修改哈希表,在这里,我们可以在不经过所有存储桶的情况下获得所有的键,为了做到这一点,我将每个键存储在另一个链表中,并在我将其添加到哈希表时存储。这样我就能很快把所有的钥匙都拿进去

当然有,但有所有警告之母

一个简单的节点数组,其中已删除的节点具有
deleted
标志,具有恒定的删除时间,但这是一个警告,它对所有其他操作的时间要求极为苛刻

编辑

答案最初提到的是排序数组,但这是错误的单词选择(对不起,非英语母语)。我的意思是索引的,就像在一个数组的经典案例中一样(想想C)——本质上意味着在访问数组元素时没有隐藏的O(>1)(设置删除标志)


另一点:我说的只是删除,而不是搜索和删除,那么hashset呢?它们为添加/删除/包含/大小提供恒定的时间性能


在java中,它被称为

是的,有几种。删除堆栈的顶部元素是O(1),这是有效的,因为您只能访问堆栈的顶部。哈希表中的任何元素都有摊销O(1)删除。

您是否希望在该O标记处进行选择性(每个对象)删除?我的想法是,如果这是一个X时间所需的大量对象集合,但之后它们都被丢弃,那么一个内存池就可以工作了,您可以将其标记为“空闲”,并理解从中分配的所有内存现在都是无效的(如果您想要一个示例,请在卸载游戏关卡准备加载新关卡时使用)


内存池只是具有特定大小的内存块,通常用于特定目的。最困难的部分是为它编写分配例程,可能还有解除分配。但是,当您完全使用完该池后,您可以简单地重置跟踪信息,以有效地“擦除”其所有数据,并使其再次可用。

我不确定我是否在遵循-似乎您希望维护元素的两个链表,以便您可以快速迭代它们-并且仍然获得
O(1)
-因此您可以使用哈希集

你在正确的轨道上。在java中,您所描述的称为

其思想是:您有两种数据结构:

  • 元素的LinkedList[双链接列表]
  • HashMap:Elements->Nodes-哈希映射中的每个键都映射到链表中的相应节点
  • 使用此DS,您可以获得以下操作:

    add(x):
      if map.containsKey(x):
        return
      list.addLast(x)
      map.put(x,list.getLastNode()) 
    
    delete(x):
      if (map.containsKey(x) == false):
        return
      list.deleteNode(map.get(x))
      map.delete(x)
    

    请注意,添加和删除都是
    O(1)
    ,它们只在映射和列表上执行最后数量的
    O(1)
    操作。

    LinkedHashSet或LinkedHashMap。 HashSet在内部使用HashMap,因此如果不需要密钥,可以使用HashSet。
    LinkedHashMap维护一个贯穿其所有条目的双链接列表。该链表定义了迭代顺序,这通常是将关键点插入地图的顺序,地图使您能够更快地搜索关键点

    Java定义的库类没有提供开箱即用的直接入队和出队功能,但只需对源代码稍加修改,就可以得到问题的答案。

    删除该对象就是O(1),或者从堆栈中删除它就是O(1)(想想看,他问的是哪一个,我想知道?)@James我的意思是从堆栈中删除,但是从任何数据结构中“删除”意味着从数据结构中删除。真正删除数据(即使数据对其他代码不可用)是特定于语言的。然而,这个问题并没有为特定的语言指定一个标记。因此,正如您所提到的,在这个上下文中,任何不需要迭代的数据结构都是O(1)?@James如果您根本不需要迭代,那么删除就是O(1)。然而,在很多情况下,迭代是隐藏的。例如,要从数组中删除一个元素,必须移动数组中所有后面的元素,这样才能真正遍历它。FP中的经典链表没有这个问题:如果使用链表实现堆栈,只需将头指针向前设置一个元素即可删除堆栈的头。恒定时间。这个例子并不适用。要查找要删除的元素,需要执行二进制搜索,这需要日志时间。是的,找到元素后,设置标志是一个固定时间操作,但不管列表是否排序,都是如此。@AdammiHalc问题不是关于查找元素,而是关于删除元素。您需要先找到它的假设是合理的,但不一定正确:如果在迭代数组时决定删除元素,则是错误的。@hvd Oops。我的错误。我正在删除错误的注释(无法编辑),我将只发布有用的部分。我先前注释的有用部分:一旦找到元素,删除是便宜的,但是这个答案明确地调用了一个排序列表。为什么要指定列表必须排序,除非您关心在列表中查找元素?@AdamMihalcin我之前评论的有用部分:好的观点:)很难知道您是否正在查找特定的元素delete[元素作为输入给定]?最小删除?第一个/最后一个元素删除?@amcnabb:这是他们在采访中问我的:(“但我正在修改哈希表,这样我们就可以在不经过所有存储桶的情况下获得所有的密钥”这听起来不标准。你能详细介绍一下你是如何做到这一点的吗?以及你选择删除哪些元素(根据@amit的建议)?@amit:我已经放弃了