经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++实现支持泛型的LFU详解
来源:jb51  时间:2021/9/28 9:55:00  对本文有异议

首先定义LFU存储数据节点ListNode的结构, 此结构支持键K和值V的模板,为了在有序元素中实现比较(严格小于),这里需要重载小于号,如果此数据的使用频次最少,则小于结果为true,如果频次相等,轮次早的数据最小。

  1. template<typename K, typename V>
  2. struct ListNode {
  3. K key;
  4. V value;
  5. int freq;
  6. long cur;
  7. bool operator<(const ListNode &x) const {
  8. if (freq < x.freq)
  9. return true;
  10. else if (freq == x.freq)
  11. return cur < x.cur;
  12. else
  13. return false;
  14. }
  15. };

然后我们来实现lfu类,我们用unordered_map去存key值对应的ListNode,用set<ListNode<K,V>> freq来充当频次的存储容器,使用set的好处是自动排序,频次小的数据迭代器会被排到freq的begin(),删除是只需要erase掉begin所指向的迭代器即可。我们来具体分析get和put操作

  • get操作首先去map中查询此key对应ListNode是否存在,如果此数据存在,将其对应的频次+1(这里用reinsert函数实现),如果数据不存在,返回-1。
  • put操作也要去map中查询此key对应ListNode是否存在,若存在,直接将ListNode的value更新,并且将其对应的频次+1(同上),否则,在map对应此键值的桶中插入ListNode,然后在freq中将其对应的频次设为1并插入。

完整代码如下:

  1. #include <map>
  2. #include <set>
  3. #include <unordered_map>
  4. using namespace std;
  5. template<typename K, typename V>
  6. struct ListNode {
  7. K key;
  8. V value;
  9. int freq;
  10. long cur;
  11. bool operator<(const ListNode &x) const {
  12. if (freq < x.freq)
  13. return true;
  14. else if (freq == x.freq)
  15. return cur < x.cur;
  16. else
  17. return false;
  18. }
  19. };
  20. template<typename K, typename V>
  21. class lfu {
  22. private:
  23. long cur_rount;
  24. int capacity;
  25. unordered_map<int, ListNode<K, V>> m;
  26. set<ListNode<K, V>> freq;
  27. public:
  28. lfu(int capacity) {
  29. capacity = capacity;
  30. cur_rount = 0;
  31. }
  32. V get(K key) {
  33. auto it = m.find(key);
  34. if (it == m.end())
  35. return -1;
  36. V value = it->second.value;
  37. reinsert(it->second);
  38. return value;
  39. }
  40. void put(K key, V value) {
  41. if (capacity == 0) return;
  42. auto it = m.find(key);
  43. if (it != m.end()) {
  44. it->second.value = value;
  45. reinsert(it->second);
  46. return;
  47. }
  48. if (m.size() == capacity) {
  49. const ListNode<K, V> &node = *freq.begin();
  50. m.erase(node.key);
  51. freq.erase(node);
  52. }
  53. ListNode<K, V> node{key, value, 1, ++cur_rount};
  54. m[node.key] = node;
  55. freq.insert(node);
  56. }
  57. void reinsert(ListNode<K, V> &node) {
  58. freq.erase(node);
  59. ++node.freq;
  60. node.cur = ++cur_rount;
  61. freq.insert(node);
  62. }
  63. };

这里写了一个简单的主函数去验证,K和V都使用int进行实例化。

在这里插入图片描述

可以看到第一次查询,得到key=1的值为8,符合预期,在插入key=7 value=10的ListNode后,LFU频次最低的Key=5 ListNode。此时再去get Key=5的值会得到一个-1,符合预期。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注w3xue的更多内容!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号