You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中按HashMap的值将键存入BinaryHeap以获取TopK高频词?

Rust实现获取HashMap中频率最高的前k个字符串

针对你用Java实现的需求,下面是对应的Rust实现方案,核心是利用BinaryHeap(Rust的堆结构)模拟JavaPriorityQueue的行为:

方案一:自定义结构体实现排序逻辑

这种方式更直观,适合需要复杂排序规则的场景:

use std::collections::{BinaryHeap, HashMap};
use std::cmp::Ordering;

// 定义存储单词和频率的结构体
#[derive(Debug, PartialEq, Eq)]
struct WordCount<'a> {
    word: &'a str,
    count: i32,
}

// 实现Ord trait,定义排序规则:
// 1. 频率小的优先级更高(模拟Java小顶堆)
// 2. 频率相同时,字典序小的优先级更高
impl<'a> Ord for WordCount<'a> {
    fn cmp(&self, other: &Self) -> Ordering {
        match self.count.cmp(&other.count) {
            Ordering::Equal => self.word.cmp(&other.word),
            order => order,
        }
    }
}

impl<'a> PartialOrd for WordCount<'a> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

// 核心函数:获取前k个高频单词
fn top_k_frequent(words: HashMap<&str, i32>, k: usize) -> Vec<&str> {
    let mut heap = BinaryHeap::new();

    for (word, count) in words {
        heap.push(WordCount { word, count });
        // 维护堆大小为k,超过则弹出当前优先级最高(频率最小)的元素
        if heap.len() > k {
            heap.pop();
        }
    }

    // 堆中元素是按频率从小到大排列的,逆序后得到从高到低的结果
    let mut result = Vec::with_capacity(k);
    while let Some(wc) = heap.pop() {
        result.push(wc.word);
    }
    result.reverse();
    result
}

fn main() {
    let mut map = HashMap::new();
    map.insert("hello", 2);
    map.insert("world", 3);
    map.insert("program", 1);

    let top_3 = top_k_frequent(map, 3);
    println!("{:?}", top_3); // 输出: ["world", "hello", "program"]
}

方案二:利用元组和Reverse简化实现

Rust的元组默认支持按元素顺序比较,结合Reverse可以快速实现小顶堆,无需自定义结构体:

use std::collections::{BinaryHeap, HashMap};
use std::cmp::Reverse;

fn top_k_frequent(words: HashMap<&str, i32>, k: usize) -> Vec<&str> {
    let mut heap = BinaryHeap::new();

    for (word, count) in words {
        // 用Reverse包装元组,让BinaryHeap成为小顶堆:
        // 先比较频率(小的在前),频率相同则比较单词字典序(小的在前)
        heap.push(Reverse((count, word)));
        if heap.len() > k {
            heap.pop();
        }
    }

    // 弹出堆元素并逆序,得到频率从高到低的结果
    let mut result = Vec::with_capacity(k);
    while let Some(Reverse((_, word))) = heap.pop() {
        result.push(word);
    }
    result.reverse();
    result
}

fn main() {
    let mut map = HashMap::new();
    map.insert("hello", 2);
    map.insert("world", 3);
    map.insert("program", 1);

    let top_3 = top_k_frequent(map, 3);
    println!("{:?}", top_3); // 输出: ["world", "hello", "program"]
}

关键逻辑说明

  • Rust的BinaryHeap默认是最大堆,而Java的PriorityQueue默认是最小堆,所以我们通过自定义排序规则或Reverse包装,让Rust的堆模拟小顶堆的行为。
  • 维护堆的大小为k:遍历所有元素时,若堆大小超过k则弹出堆顶元素(当前频率最小的元素),最终堆中保留的就是频率最高的k个元素。
  • 最后逆序堆中元素,得到频率从高到低的结果(频率相同时,字典序大的在前,符合你Java代码的逻辑)。

内容的提问来源于stack exchange,提问作者Aditya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:33:30