如何在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
相关产品推荐
相关产品推荐

