Java 存储计数最小草图的前k个结果

Java 存储计数最小草图的前k个结果,java,data-structures,heap,count-min-sketch,Java,Data Structures,Heap,Count Min Sketch,我需要在流中存储前k个最频繁的元素。为了估计频率,我使用count min草图算法。我的流由键(作为字符串)组成。因此,基本上每次我在流中遇到一个新键时,我都会通过查看count min sketch数据结构来计算当前键的频率。但是,我无法存储前k个最常用的键 我的第一个想法是将它们存储在一个最小的堆中,大小固定为k。我将[frequency,key]与比较器comnpare frequency一起存储在这个min堆中。所以每次我得到一个键的频率,我试着看看堆大小是否超过k,如果是,那么我将当前

我需要在流中存储前k个最频繁的元素。为了估计频率,我使用count min草图算法。我的流由键(作为字符串)组成。因此,基本上每次我在流中遇到一个新键时,我都会通过查看count min sketch数据结构来计算当前键的频率。但是,我无法存储前k个最常用的键

我的第一个想法是将它们存储在一个最小的堆中,大小固定为k。我将[frequency,key]与比较器comnpare frequency一起存储在这个min堆中。所以每次我得到一个键的频率,我试着看看堆大小是否超过k,如果是,那么我将当前键的频率与最小堆中的最高(最小)频率进行比较,如果我当前键的频率更大,那么我弹出顶部,并将我的键插入堆中

然而,我意识到最小堆不是一个集合,这意味着它允许复制。假设我有一个非常热的密钥,我一直在流中计算它,所以每次我将这个[frequency,key]插入堆中,最终我的堆将充满相同的密钥,只有不同的频率


因此,我想知道是否有一种好方法可以在count min sketch中存储前k个不同的更频繁元素。

有必要维护堆中已有的
[key,]
对的哈希映射
position
指堆内键的索引(假设基于数组的堆)。当密钥到达时,您检查两个条件:
-密钥在hashmap中
-它的频率已经改变了

如果两者都是真的,那么您会在
O(1)
时间中找到堆中的键,因为它的位置已经存储在hashmap中,然后修改键的频率,并根据频率是增加还是减少,从该位置向下或向上冒泡(
O(logn)
)。更改位置后,使用新的频率和位置值更新该键的hashmap条目

如果第一个值为false,则遵循通常的逻辑,即将键与根进行比较,如果堆已满且键的频率大于根的频率,则将根从堆中弹出并从hashmap中删除,同时将键插入堆和hashmap


如果键在hashmap中,但其频率未更改,则不执行任何操作。

您还可以维护所有三个数据结构1。计算min sketch以存储流2中遇到的所有内容。大小为K3的最小堆。大小为k的哈希映射

在热项目的情况下-增加计数并从count min sketch获得新的频率,假设此项目已存在于min heap中,则从哈希映射获得项目并增加频率


当您遇到一个不同的项目,其频率刚刚增加并进入著名的min heap时,您可以同时从min heap和哈希映射中逐出根,因此基本上min heap可以帮助您维护前k个频繁项目和哈希映射,以随机访问这些频繁项目。请注意,min heap和hash map都可以映射到相同的内存地址,因此更新频率只能对hash map中存储的项进行更新,这是一个好主意。Java的优先级队列在操作后不提供索引。所以我坚持优先排队。但您提醒我,我可以自己实现一个具有索引支持的二进制堆。