什么是支持Enque、Dequeue、Peak、Min和Max操作并且所有这些操作的时间复杂度均为O(1)的队列的正确数据结构。
最显然的数据结构是链表,但是Min、Max操作将会是O(n)。优先队列是另一个完美的选择,但是Enqueue、Dequeue应该按照队列(FIFO)的正常方式工作。
另外一个我想到的选择是堆,但我无法想象如何使用堆来设计具有Min、Max操作的队列。
非常感谢任何帮助。
什么是支持Enque、Dequeue、Peak、Min和Max操作并且所有这些操作的时间复杂度均为O(1)的队列的正确数据结构。
最显然的数据结构是链表,但是Min、Max操作将会是O(n)。优先队列是另一个完美的选择,但是Enqueue、Dequeue应该按照队列(FIFO)的正常方式工作。
另外一个我想到的选择是堆,但我无法想象如何使用堆来设计具有Min、Max操作的队列。
非常感谢任何帮助。
// N your node class; can return K, comparable, used for min() and max()
LinkedList<N> list; // sorted by arrival
TreeMap<K,HashMap<N>> tree; // sorted by K
list
的末尾,并通过其键将相同的节点添加到tree
中的节点的HashMap
。时间复杂度为O(log n)。list
的开头以及从其在树中的节点中的HashMap
中删除该节点。时间复杂度为O(log n)。如果您知道所有键都是唯一的,则可以简化此过程(通过删除HashMap)。但是,这不会影响渐近成本:它们仍将保持不变。
实际上,在O(log n)和O(1)之间的差异非常小,以至于C++ STL中的默认映射实现是基于O(log n)的(使用Tree而不是Hash)。
Insert
、Max
和RemoveMax
操作,建立它们的方法有很多种,但二叉堆是最好的。Insert
、Min
、RemoveMin
、Max
和RemoveMax
所有操作的单个优先队列更加复杂。一种用于单个数据结构的方式是从二叉堆中改编而来,在以下论文中进行了描述:
这种方法快速且占用内存较少,但需要非常小心地实现。Atkinson, Michael D., et al. "Min-max heaps and generalized priority queues." Communications of the ACM 29.10 (1986): 996-1000.
这种结构是不存在的!
有一个简单的方法可以证明这个结论。
我们都知道,排序问题的复杂度是O(nlogn)。 但是,如果你所说的结构存在,就会有一种解决方案:
这意味着排序问题可以用O(n)解决。但这是不可能的。
假设:
您只关心性能,而不关心空间/内存等。
解决方案:
索引是一个集合,而不是列表(对于列表也可以工作,但可能需要一些额外的处理)
您可以同时使用队列和哈希表。
示例:
假设顺序是5 4 7 1 8 3
队列 -> 547813
哈希表 -> 134578
入队:
1)将对象插入正确的哈希表桶中,Min / Max始终是第一个和最后一个索引。(请参见排序的哈希表)
2)接下来,像正常情况下一样将其插入队列。
3)您可以/应该将两者链接起来。一个想法是使用哈希表值作为指向队列的指针。
使用大型哈希表的两个操作都将是O(1)
出队:
1)弹出第一个元素O(1)
2)从哈希表中删除元素O(1)
最小值/最大值:
1)查看您的哈希表。根据所使用的语言,您可以在理论上通过查看表头或表尾来找到它。
有关排序哈希表的更好解释,请参见 https://dev59.com/XkvSa4cB1Zd3GeqPcCQB。
注意: 我想指出,我不知道有什么“正常”的数据结构能够满足您的要求。但这并不意味着不可能。如果您要尝试实现这个数据结构,很可能您将不得不根据自己的需求进行实现,并且无法使用当前可用的库。您可能需要考虑使用低级语言(如汇编语言)才能实现此目的,但如果您对 C 或 Java 熟悉,也许也能做到。
祝你好运
编辑: 我没有解释排序哈希表,因此添加了另一个 SO 的链接来解释它们。