在O(1)中实现extract-min

时间:2011-02-02 04:41:57

标签: algorithm

  

可能重复:
  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)。

任何帮助或提示都将不胜感激。

2 个答案:

答案 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)