可能重复:
Implement a queue in which push_rear(), pop_front() and get_min() are all constant time operations.
我需要实现一个FIFO数据结构,其中Enqueue,Dequeue和Extract-Min的摊销成本为O(1)。
我已经考虑过使用一个常规队列,它会使用链接列表将O(1)入队并出列,然后对于Extract-Min,我会通过数组来获取min并删除它。虽然费用为O(n),但不会将摊销成本计入O(1)。
任何帮助或提示都将不胜感激。
答案 0 :(得分:1)
您可以使用额外成员实现队列,该成员始终指向队列值最小的节点。必须稍微修改Enqueue(),如下面的伪代码所示:
void enqueue( data_t val )
{
back->m_data = val; // back is a pointer to the end of the queue.
// m_Min should be initialized with a large value.
if (back->m_data <= m_Min->m_data)
{
m_Min = back;
}
else // => back->m_data > m_Min->m_data
{
swap(back->m_data, m_Min->m_data);
m_Min = back;
}
}
上述修改将确保enqueue,dequeue和extract_min都在O(1)中运行。
data_t dequeue( )
{
data_t front_data = front->m_data;
prev_front = front;
front = front->next;
dump prev_front;
return front_data;
}
因此当front
到达m_Min
时,队列中只有一个元素的值最小。
data_t min()
{
return m_Min->m_data;
}
编辑: enqueue()
中的if-block是从我以前的版本修改过来的。 enqueue()基本上会在最后推送新值。但如果它大于当前最小值(保留在队列的最后一个节点中),则与前一节点交换。
例如,如果输入序列是5,3,7,1,4,6,8。
1.
front -> 5 <- back
^min
2.
front -> 5 3 <- back.
^min
front -> 5 3 <- back.
^min
3.
front -> 5 3 7 <- back
^min
front -> 5 7 3 <- back
^min
4.
front -> 5 7 3 1 <- back
^min
front -> 5 7 3 1 <- back
^min
5.
front -> 5 7 3 1 4 <- back
^min
front -> 5 7 3 4 1 <- back
^min
6.
front -> 5 7 3 4 1 6 <- back
^min
front -> 5 7 3 4 6 1 <- back
^min
7.
front -> 5 7 3 4 6 1 8 <- back
^min
front -> 5 7 3 4 6 8 1 <- back
^min
假设您将3个项目出列,队列将如下所示:
front -> 4 6 8 1 <- back
^min
因此,当front
到达min
时,队列将只有一个元素min
。
答案 1 :(得分:0)
我建议一起使用2个基础数据结构来构建新的数据结构。
首先,您可以使用正常的队列,可以在O(1)中提供en-Queue和de-Queue。
然后使用辅助堆栈来跟踪最小值的指针。
插入第一项时,从头开始,只需deq.push_back()和stack.push();
然后是以下项目:
排队:推回队列,将新项目与堆栈顶部进行比较,如果新项目较小,则按下它,否则不执行任何操作。 O(1)中的所有操作
Dequeue:获取dequeue的头部,将它与堆栈的顶部进行比较,如果它们是相同的,这意味着dequed是最小的,然后弹出堆栈,否则,在堆栈上什么都不做。 O(1)中的所有操作。
Extract-Min:获得堆栈的顶部,它是最小的。 O(1)