使用窗口大小和长输入运行中位数

时间:2015-03-23 14:54:06

标签: c++ algorithm data-structures heap

给定一系列数据(它可能有重复数据),一个固定大小的移动窗口,在每次迭代时从数据序列的开头移动窗口,这样 (1)从窗口中删除最旧的数据元素,并将新的数据元素推入窗口 (2)在每次移动时找到窗口内数据的中位数。

这里窗口大小为7,我们称之为m。 m =窗口大小 n =序列中元素的数量,可以是1000或10000

Median for 4, 6, 99, 10, 90, 12, 17,1,21,32  : 12
Median for 6, 99, 10, 90, 12, 17, 1,21,32  : 12
Median for 99, 10, 90, 12, 17, 1, 21,32 : 17
Median for 10, 90, 12, 17, 1, 21, 32 : 17

我每次都借助于m个元素的Quicksort来实现这个东西,(中间三个作为支点)。但这需要很多时间。每次排序都需要。我应该按照提到的here

实现最小和最大堆解决方案

Min-Max堆解决方案中的问题:

当新数据被推入窗口时,从其中一个堆中删除最旧的数据,并将新数据与max和min堆的顶部进行比较,以便确定哪个堆要放的数据。然后,找到中间值就像在第一次迭代中一样。

  1. 如何查找从堆中删除最旧的数据,我们如何维护它。根据给定的示例,第二时间4是最旧的元素,第三时间6是最旧的元素。我们如何从堆中删除它。

  2. 上述问题的后续问题,如何在堆中查找数据元素是一个问题。堆是二叉树而不是二叉搜索树。

  3. 任何帮助都将不胜感激。

    编辑:我已经有输入数据,所以没有插入发生。只发生在固定大小的队列或窗口而不是实际的输入序列。

    由于

2 个答案:

答案 0 :(得分:0)

对于正在运行的数据中位数(移动窗口,其中发生插入和删除),使用单个二叉搜索树而不是移动窗口中元素的最小 - 最大堆可能更有用。 / p>

二叉搜索树也是一个订单统计树,存储以每个节点为根的子树的大小。

这棵树能够在O(log n)中进行插入,删除和中值计算。

在上面给出的例子中,每个操作都有时间复杂度O(log 7)。

答案 1 :(得分:0)

除了堆DS之外,还要保存一个指针(或引用)队列,其中队列中的每个元素都指向表示堆中相关条目的节点。

当您将窗口移动1:

  1. 出列旧元素
  2. 按照指针,找到二进制堆中的节点。
  3. "开关" "最后"与刚刚找到的节点相关的节点(最低级别中最右边的元素)
  4. 删除新的" last"节点
  5. 重新heapify
  6. 使用下一个元素
  7. 创建二进制堆的新条目
  8. 将刚添加的节点的指针排入队列
  9. 重新计算中位数