{"id":100,"date":"2021-04-28T08:59:45","date_gmt":"2021-04-28T00:59:45","guid":{"rendered":"https:\/\/blog.king011.com\/?p=100"},"modified":"2021-04-28T08:59:48","modified_gmt":"2021-04-28T00:59:48","slug":"%e5%be%9e%e9%9b%b6%e9%96%8b%e5%a7%8b%e7%9a%84%e7%b7%a9%e5%ad%98%e7%94%9f%e6%b4%bb-lfu","status":"publish","type":"post","link":"https:\/\/blog.king011.com\/?p=100","title":{"rendered":"\u5f9e\u96f6\u958b\u59cb\u7684\u7de9\u5b58\u751f\u6d3b-LFU"},"content":{"rendered":"\n<p>FIFO \u7b97\u6cd5\u7684\u554f\u984c\u5728\u65bc\u71b1\u9ede\u6578\u64da\u548c\u51b7\u9580\u6578\u64da\u64c1\u6709\u76f8\u540c\u7684\u6b0a\u91cd\uff0c\u6240\u8b02\u71b1\u9ede\u6578\u64da\u5c31\u662f\u7d93\u5e38\u88ab\u8a2a\u554f\u7684\u6578\u64da\uff0c\u610f\u5473\u7740\u71b1\u9ede\u6578\u64da\u5c07\u7372\u5f97\u66f4\u591a\u7684 Get \u67e5\u8a62\uff0cLFU \u4fbf\u662f\u5efa\u7acb\u5728\u6b64\u60f3\u6cd5\u4e4b\u4e0a\u3002LFU \u95dc\u6ce8\u7de9\u5b58\u88ab\u8a2a\u554f\u7684\u6b21\u6578\u4e26\u4f9d\u6b64\u4f86\u5224\u65b7\u6578\u64da\u7684\u71b1\u5ea6\uff0c\u8d8a\u5e38\u88ab\u8a2a\u554f\u7684\u6578\u64da\u5176\u71b1\u5ea6\u8d8a\u9ad8\uff0c\u800c\u8d8a\u51b7\u9580\u7684\u6578\u64da\u71b1\u5ea6\u8d8a\u4f4e\u3002<\/p>\n\n\n\n<p>LFU \u7232\u6bcf\u7b46\u6578\u64da\u7ba1\u7406\u4e00\u500b\u8a08\u6578\u4f86\u8868\u793a\u5176\u71b1\u5ea6\uff0c\u6bcf\u7576\u6578\u64da\u88ab Get \u5c31\u5c07\u5176\u8a08\u6578 +1\uff0c\u9019\u6a23\u7d93\u5e38\u88ab\u8a2a\u554f\u7684\u71b1\u9ede\u6578\u64da\u8a08\u6578\u5c31\u6703\u5f88\u9ad8\uff0c\u800c\u51b7\u9580\u6578\u64da\u7684\u8a08\u6578\u5c31\u6703\u5f88\u4f4e\uff0c\u7576\u7de9\u5b58\u5df2\u6eff\u6642\u5c31\u522a\u9664\u8a08\u6578\u6700\u4f4e(\u5373\u71b1\u5ea6\u6700\u5c11)\u7684\u7de9\u5b58\u4ee5\u9a30\u51fa\u7a7a\u9593\u5b58\u5132\u65b0\u7684\u7de9\u5b58\u3002<\/p>\n\n\n\n<p>\u7db2\u8def\u67e5\u770b\u5230\u7684\u8cc7\u6599\u4e26\u672a\u770b\u5230\u95dc\u65bc Put \u6642\u8a08\u6578\u7684\u64cd\u4f5c\uff0c\u4f46\u672c\u55b5\u8a8d\u7232 Put \u6642\u5982\u679c\u7de9\u5b58\u5b58\u5728\u4e5f\u61c9\u8a72\u7232\u8a08\u6578 +1 \u56e0\u7232\u9019\u6a23\u5be6\u73fe\u7c21\u55ae\uff0c\u800c\u4e14\u7121\u8ad6\u662f Get Put \u90fd\u662f\u95dc\u6ce8\u7684\u7de9\u5b58\u7684 key \u8a08\u6578\u61c9\u8a72\u662f\u548c key \u7d81\u5b9a\uff0c\u7576\u7136\u77e5\u9053\u539f\u7406\u5728 Put \u6642\u662f\u5426\u8981\u5c07\u8a08\u6578\u589e\u52a0\u4f60\u53ef\u4f9d\u81ea\u5df1\u7684\u9700\u8981\u5be6\u73fe\u3002<\/p>\n\n\n\n<p>LFU \u9700\u8981\u7de9\u5b58\u6309\u7167\u71b1\u5ea6\u8a08\u6578\u6392\u5e8f\uff0c\u60f3\u4e0b\u53ef\u4ee5\u4f7f\u7528 \u4e8c\u53c9\u6392\u5e8f\u6a39\uff0c\u6700\u5c0f\u5806\uff0c\u6216\u8005\u93c8\u8868\uff0c\u901a\u5e38\u7684\u505a\u6cd5\u662f\u4f7f\u7528\u93c8\u8868\u548c\u6700\u5c0f\u5806\uff0c\u4e8c\u53c9\u6392\u5e8f\u6a39\u662f\u5b8c\u6574\u7684\u6392\u5e8f\u5176\u5be6\u6c92\u6709\u5fc5\u8981\u6211\u5011\u6bcf\u6b21\u53ea\u9700\u8981\u8a08\u6578\u6700\u5c0f\u7684\u503c\u9019\u500b\u7279\u6027\u6700\u5c0f\u5806\u6700\u9069\u5408\u4e86\uff0c\u6b64\u5916\u5982\u679c\u7528\u93c8\u8868\u7684\u8a71\u93c8\u8868\u53ef\u4ee5\u6309\u7167\u8a08\u6578\u5927\u5c0f\u4e92\u76f8\u9023\u63a5\u56e0\u7232\u6bcf\u6b21\u8a08\u6578\u90fd+1\uff0c\u7576\u71b1\u9ede\u589e\u52a0\u6642\u8abf\u6574\u93c8\u8868\u4f4d\u7f6e\u53ea\u9700\u8981\u4e00\u76f4\u548cNext\u6bd4\u8f03\u5982\u679c\u8a08\u6578\u4e0d\u5927\u65bc\u81ea\u5df1\u7684\u5c31\u4ea4\u4e92\u4f4d\u7f6e\u5373\u53ef(\u6240\u4ee5\u4ea4\u63db\u6b21\u6578\u548c\u76f8\u540c\u71b1\u5ea6\u7de9\u5b58\u7684\u6578\u91cf\u76f8\u95dc\uff0c\u7576\u5b58\u5728\u5927\u91cf\u540c\u71b1\u5ea6\u7de9\u5b58\u6642\u8abf\u6574\u93c8\u8868\u7684\u6d88\u8017\u5c07\u589e\u52a0)\u3002<\/p>\n\n\n\n<p>\u6700\u5c0f\u5806\u662f\u672c\u55b5\u8a8d\u7232\u6700\u9069\u5408\u5be6\u73fe LFU \u6dd8\u6c70\u7b97\u6cd5\u7684\u7d50\u69cb\uff0c\u525b\u597d golang \u6a19\u6e96\u5eab\u4e5f\u6709\u63d0\u4f9b\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5be6\u73fe LFU<\/h2>\n\n\n\n<p>\u9996\u5148\u6211\u5011\u4f86\u7232\u7de9\u5b58\u6578\u64da\u5b9a\u7fa9\u4e00\u500b lfuValue \u985e\u578b\u548c FIFO\u4e2d\u7684\u5b9a\u7fa9\u7684 cacheValue \u76f8\u6bd4\u9700\u8981\u4e00\u500b\u65b0\u7684\u5c6c\u6027\u4f86\u8a18\u9304\u71b1\u5ea6\uff0c\u53e6\u5916\u9084\u9700\u8981\u4e00\u500b\u5c6c\u6027\u8a18\u9304\u5728\u5806\u4e2d\u7684\u4f4d\u7f6e\u4ee5\u4fbf\u522a\u9664\u6642\u4f7f\u7528\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u7232\u7de9\u5b58\u6578\u64da\u5b9a\u7fa9\u4e00\u500b\u985e\u578b\ntype lfuValue struct {\n\tKey   interface{}\n\tValue interface{}\n\tHot   int\n\tIndex int \/\/ \u8a18\u9304\u5728\u5806\u4e2d\u7684\u4f4d\u7f6e\n}<\/code><\/pre>\n\n\n\n<p>\u7136\u5f8c golang \u6c92\u6709\u6a21\u677f\uff0c\u6240\u4ee5\u6a19\u6e96\u5eab\u7684\u6700\u5c0f\u5806\u5f88\u96e3\u7528\uff0c\u6211\u5011\u5148\u5305\u88dd\u4e00\u4e0b\u4e26\u4e14\u7232 lfuValue \u5be6\u73fe\u6a19\u6e96\u5eab\u4e2d\u6700\u5c0f\u5806\u9700\u8981\u7684\u63a5\u53e3\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u5be6\u73fe \u6a19\u6e96\u5eab\u9700\u8981\u7684\u63a5\u53e3\ntype lfuValueHeap &#91;]*lfuValue\n\nfunc (a lfuValueHeap) Len() int {\n\treturn len(a)\n}\nfunc (a lfuValueHeap) Swap(i, j int) {\n\ta&#91;i], a&#91;j] = a&#91;j], a&#91;i]\n\t\/\/ \u66f4\u65b0\u5728\u5806\u4e2d\u7684\u4f4d\u7f6e\n\ta&#91;i].Index = i\n\ta&#91;j].Index = j\n}\nfunc (a lfuValueHeap) Less(i, j int) bool {\n\treturn a&#91;i].Hot &lt; a&#91;j].Hot\n}\nfunc (h *lfuValueHeap) Push(x interface{}) {\n\tv := x.(*lfuValue)\n\tv.Index = len(*h) \/\/ \u6dfb\u52a0\u5230\u5806\u6642 \u8a18\u9304\u4f4d\u7f6e\n\t*h = append(*h, v)\n}\nfunc (h *lfuValueHeap) Pop() interface{} {\n\told := *h\n\tn := len(old)\n\tx := old&#91;n-1]\n\t*h = old&#91;0 : n-1]\n\told&#91;n-1] = nil\n\treturn x\n}\n\n\/\/ \u5305\u88dd\u4e00\u4e0b \u6700\u5c0f\u5806\ntype lfuHeap struct {\n\theap lfuValueHeap\n}\n\nfunc newLFUHeap(capacity int) *lfuHeap {\n\theap := make(lfuValueHeap, 0, capacity)\n\treturn &amp;lfuHeap{\n\t\theap: heap,\n\t}\n}\nfunc (h *lfuHeap) Push(val *lfuValue) int {\n\theap.Push(&amp;h.heap, val)\n\treturn val.Index\n}\nfunc (h *lfuHeap) Len() int {\n\treturn h.heap.Len()\n}\n\nfunc (h *lfuHeap) Remove(i int) *lfuValue {\n\tv := heap.Remove(&amp;h.heap, i)\n\tif v == nil {\n\t\treturn nil\n\t}\n\treturn v.(*lfuValue)\n}\nfunc (h *lfuHeap) Fix(i int) {\n\theap.Fix(&amp;h.heap, i)\n}<\/code><\/pre>\n\n\n\n<p>\u5df2\u7d93\u6709\u4e86\u4e00\u500b\u6700\u5c0f\u5806 lfuHeap \u6211\u5011\u4f86\u770b\u4e0b LFU \u9700\u8981\u7684\u5c6c\u6027\uff0c\u548c FIFO \u985e\u4f3c\u4e00\u500b Map \u5b58\u5132\u7de9\u5b58\uff0c\u4e00\u500b capacity \u5b58\u5132\u6700\u5927\u5bb9\u91cf\uff0c\u53e6\u5916\u4e00\u500b hot \u5be6\u73fe\u6dd8\u6c70\u7b97\u6cd5\u9019\u88cf\u4f7f\u7528\u4e0a\u9762\u5be6\u73fe\u7684\u6700\u5c0f\u5806\u5373\u53ef\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ LFU \u7232\u7de9\u5b58\u5b9a\u7fa9\u4e00\u500b\u81ea\u5b9a\u7fa9\u985e\u578b\ntype LFU struct {\n\t\/\/ \u6b64\u5b57\u6bb5\u8a2d\u7f6e\u7de9\u5b58\u5bb9\u91cf\u4e0a\u9650\n\tcapacity int\n\t\/\/ Map \u7232 \u67e5\u8a62\u7de9\u5b58\u6578\u64da\u63d0\u4f9b \u652f\u6301\n\tkeys map&#91;interface{}]*lfuValue\n\t\/\/ \u7de9\u5b58\u6dd8\u6c70\u7b97\u6cd5\u4f7f\u7528 \u4f7f\u7528\u6700\u5c0f\u5806\u6bcf\u6b21\u6dd8\u6c70 \u71b1\u5ea6\u6700\u4f4e\u7684\u5143\u7d20\n\thot *lfuHeap\n}\n\n\/\/ \u56e0\u7232golang\u6c92\u6709\u69cb\u9020\u51fd\u6578 \u63d0\u4f9b\u4e00\u500b New \u51fd\u6578 \u5275\u5efa\u7de9\u5b58\nfunc NewLFU(capacity int) *LFU {\n\tif capacity &lt; 1 {\n\t\tpanic(`capacity must &gt; 0`)\n\t}\n\treturn &amp;LFU{\n\t\tcapacity: capacity,\n\t\tkeys:     make(map&#91;interface{}]*lfuValue, capacity),\n\t\thot:      newLFUHeap(capacity),\n\t}\n}<\/code><\/pre>\n\n\n\n<p>\u9084\u662f\u7531\u6613\u5230\u96e3\u5148\u5be6\u73fe\u6700\u7c21\u55ae\u7684 Delete \u63a5\u53e3\uff0c\u67e5\u8a62\u7de9\u5b58\u5982\u679c\u5b58\u5728\u522a\u9664\u5373\u53ef\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func (c *LFU) Delete(key interface{}) {\n\tv, exists := c.keys&#91;key]\n\tif !exists {\n\t\t\/\/ \u7de9\u5b58\u4e0d\u5b58\u5728 \u76f4\u63a5\u8fd4\u56de\u5373\u53ef\n\t\treturn\n\t}\n\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5f9e Map \u548c Hot \u522a\u9664\u4e4b\n\tdelete(c.keys, key)\n\tc.hot.Remove(v.Index)\n}<\/code><\/pre>\n\n\n\n<p>\u7136\u5f8c\u662f Get \u548c FIFO \u5be6\u73fe\u5dee\u4e0d\u591a\u552f\u4e00\u7684\u5340\u5225\u662f\uff0c\u5982\u679c\u7de9\u5b58\u5b58\u5728\u5c31\u7232\u5176\u71b1\u5ea6+1\uff0c\u4e26\u4e14\u8abf\u6574\u6700\u5c0f\u5806(\u6216\u6392\u5e8f\u4f60\u4f7f\u7528\u7684\u5176\u5b83\u6578\u64da\u7d50\u69cb)\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func (c *LFU) Get(key interface{}) (value interface{}, exists bool) {\n\tv, exists := c.keys&#91;key]\n\tif !exists {\n\t\treturn\n\t}\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5c07\u7de9\u5b58\u8a2d\u7f6e\u7d66\u8fd4\u56de\u503c\n\tvalue = v.Value\n\n\t\/\/ \u589e\u52a0\u71b1\u5ea6 \u4e26\u4e14\u91cd\u65b0\u6392\u5e8f\n\tv.Hot++\n\tc.hot.Fix(v.Index) \/\/ \u6700\u5c0f\u5806\u53ea\u9700\u8981\u8abf\u6574\u4e00\u4e0b\u5806\u7d50\u69cb\u5373\u53ef\n\treturn\n}<\/code><\/pre>\n\n\n\n<p>\u6700\u5f8c\u662f Put \u7684\u5be6\u73fe\uff0c\u548c PIPO \u985e\u4f3c\u5148\u6aa2\u67e5\u662f\u5426\u5b58\u5728\u5b58\u5728\u5c31\u66f4\u65b0\u503c\u4e26\u8abf\u6574\u6700\u5c0f\u5806\uff0c\u5982\u679c\u4e0d\u5b58\u5728\u5c31\u5148\u6aa2\u67e5\u662f\u5426\u9054\u5230\u5bb9\u91cf\u4e0a\u9650\u9054\u5230\u5c31\u522a\u9664\u6700\u5c0f\u5806\u4e2d\u7b2c\u4e00\u500b\u5143\u7d20(\u71b1\u5ea6\u6700\u5c0f\u7684\u5143\u7d20)\uff0c\u6700\u5f8c\u63d2\u5165\u65b0\u7de9\u5b58\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>func (c *LFU) Put(key, value interface{}) {\n\tv, exists := c.keys&#91;key]\n\tif exists { \/\/ \u7de9\u5b58\u5b58\u5728 \u66f4\u65b0\u503c \u71b1\u5ea6 \u4e26\u4e14\u91cd\u65b0\u6392\u5e8f\n\t\tv.Hot++\n\t\tv.Value = value\n\t\tc.hot.Fix(v.Index) \/\/ \u6700\u5c0f\u5806\u53ea\u9700\u8981\u8abf\u6574\u4e00\u4e0b\u5806\u7d50\u69cb\u5373\u53ef\n\t\treturn\n\t}\n\t\/\/ \u4e0d\u5b58\u5728\u9996\u5148\u5224\u65b7\u7de9\u5b58\u662f\u5426\u5df2\u6eff\n\tif len(c.keys) == c.capacity {\n\t\t\/\/ \u7de9\u5b58\u5df2\u6eff \u522a\u9664\u71b1\u5ea6\u6700\u5c0f\u7684\u5143\u7d20\n\t\tv := c.hot.Remove(0)\n\t\tdelete(c.keys, v.Key)\n\t}\n\n\t\/\/ \u5c07\u65b0\u7de9\u5b58\u5167\u5bb9\u52a0\u5165\n\tv = &amp;lfuValue{\n\t\tKey:   key,\n\t\tValue: value,\n\t\tHot:   1,\n\t}\n\tc.hot.Push(v)\n\tc.keys&#91;key] = v\n}<\/code><\/pre>\n\n\n\n<p>\u81f3\u6b64\u6211\u5011\u4fbf\u5b8c\u6210\u4e86 LFU \u7de9\u5b58\u7b97\u6cd5\uff0c\u4e0b\u9762\u4f86\u5beb\u500b\u7c21\u55ae\u7684\u6e2c\u8a66\u793a\u4f8b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package cache\n\nimport (\n\t\"testing\"\n)\n\nfunc TestLFU(t *testing.T) {\n\ttype _Hot struct {\n\t\tKey interface{}\n\t\tHot int\n\t}\n\tmakeHot := func(key interface{}, hot int) _Hot {\n\t\treturn _Hot{\n\t\t\tKey: key,\n\t\t\tHot: hot,\n\t\t}\n\t}\n\t\/\/ \u5b9a\u7fa9\u4e00\u500b\u8f14\u52a9\u51fd\u6578\u6e2c\u8a66\u7de9\u5b58\u4e2d\u5b58\u5728\u7684 key\n\tassertExists := func(t *testing.T, lfu *LFU, key ..._Hot) {\n\t\tfor _, k := range key {\n\t\t\tv, exists := lfu.keys&#91;k.Key]\n\t\t\tif !exists {\n\t\t\t\tt.Fatalf(\"key not exists : %v\", k.Key)\n\t\t\t}\n\t\t\tif v.Hot != k.Hot {\n\t\t\t\tt.Fatalf(\"key' hot not match key=%v, %v!=%v\", k.Key, k.Hot, v.Hot)\n\t\t\t}\n\t\t}\n\t}\n\n\tc := NewLFU(3)\n\t\/\/ \u63d2\u5165 3 \u500b\u7de9\u5b58 \u6b64\u6642\u7de9\u5b58\u4e86 key \u7232 0 1 2 \u7684\u6578\u64da \u71b1\u5ea6\u5206\u5225\u7232 1\n\tfor i := 0; i &lt; 3; i++ {\n\t\tc.Put(i, i)\n\t}\n\n\t\/\/ \u9a57\u8b49 \u7de9\u5b58\u5b58\u5728\n\tassertExists(t, c, makeHot(0, 1), makeHot(1, 1), makeHot(2, 1))\n\n\t\/\/ \u8a2a\u554f \u6578\u64da key \u7232 0 2 \u7684\u6578\u64da\n\tc.Get(0)\n\tc.Get(0)\n\tc.Get(2)\n\t\/\/ \u7de9\u5b58\u71b1\u5ea6\u5df2\u7d93\u8b8a\u5316\u7232\n\t\/\/ 0 3\n\t\/\/ 1 1\n\t\/\/ 2 2\n\tassertExists(t, c, makeHot(0, 3), makeHot(1, 1), makeHot(2, 2))\n\n\t\/\/ \u63d2\u5165 key 3 \u56e0\u7232 key 1 \u71b1\u5ea6\u6700\u4f4e \u88ab\u6dd8\u6c70\n\t\/\/ 0 3\n\t\/\/ 2 2\n\t\/\/ 3 1\n\tc.Put(3, 3)\n\tassertExists(t, c, makeHot(0, 3), makeHot(2, 2), makeHot(3, 1))\n\n\t\/\/ \u63d2\u5165 key 4 \u56e0\u7232 key 3 \u71b1\u5ea6\u6700\u4f4e \u88ab\u6dd8\u6c70\n\t\/\/ 0 3\n\t\/\/ 2 2\n\t\/\/ 3 1\n\tc.Put(4, 4)\n\tassertExists(t, c, makeHot(0, 3), makeHot(2, 2), makeHot(4, 1))\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5b8c\u6574\u4ee3\u78bc<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package cache\n\nimport \"container\/heap\"\n\n\/\/ \u7232\u7de9\u5b58\u6578\u64da\u5b9a\u7fa9\u4e00\u500b\u985e\u578b\ntype lfuValue struct {\n\tKey   interface{}\n\tValue interface{}\n\tHot   int\n\tIndex int\n}\n\n\/\/ \u5be6\u73fe \u6a19\u6e96\u5eab\u9700\u8981\u7684\u63a5\u53e3\ntype lfuValueHeap &#91;]*lfuValue\n\nfunc (a lfuValueHeap) Len() int {\n\treturn len(a)\n}\nfunc (a lfuValueHeap) Swap(i, j int) {\n\ta&#91;i], a&#91;j] = a&#91;j], a&#91;i]\n\t\/\/ \u66f4\u65b0\u5728\u5806\u4e2d\u7684\u4f4d\u7f6e\n\ta&#91;i].Index = i\n\ta&#91;j].Index = j\n}\nfunc (a lfuValueHeap) Less(i, j int) bool {\n\treturn a&#91;i].Hot &lt; a&#91;j].Hot\n}\nfunc (h *lfuValueHeap) Push(x interface{}) {\n\tv := x.(*lfuValue)\n\tv.Index = len(*h) \/\/ \u6dfb\u52a0\u5230\u5806\u6642 \u8a18\u9304\u4f4d\u7f6e\n\t*h = append(*h, v)\n}\nfunc (h *lfuValueHeap) Pop() interface{} {\n\told := *h\n\tn := len(old)\n\tx := old&#91;n-1]\n\t*h = old&#91;0 : n-1]\n\told&#91;n-1] = nil\n\treturn x\n}\n\n\/\/ \u5305\u88dd\u4e00\u4e0b \u6700\u5c0f\u5806\ntype lfuHeap struct {\n\theap lfuValueHeap\n}\n\nfunc newLFUHeap(capacity int) *lfuHeap {\n\theap := make(lfuValueHeap, 0, capacity)\n\treturn &amp;lfuHeap{\n\t\theap: heap,\n\t}\n}\nfunc (h *lfuHeap) Push(val *lfuValue) int {\n\theap.Push(&amp;h.heap, val)\n\treturn val.Index\n}\nfunc (h *lfuHeap) Len() int {\n\treturn h.heap.Len()\n}\n\nfunc (h *lfuHeap) Remove(i int) *lfuValue {\n\tv := heap.Remove(&amp;h.heap, i)\n\tif v == nil {\n\t\treturn nil\n\t}\n\treturn v.(*lfuValue)\n}\nfunc (h *lfuHeap) Fix(i int) {\n\theap.Fix(&amp;h.heap, i)\n}\n\n\/\/ LFU \u7232\u7de9\u5b58\u5b9a\u7fa9\u4e00\u500b\u81ea\u5b9a\u7fa9\u985e\u578b\ntype LFU struct {\n\t\/\/ \u6b64\u5b57\u6bb5\u8a2d\u7f6e\u7de9\u5b58\u5bb9\u91cf\u4e0a\u9650\n\tcapacity int\n\t\/\/ Map \u7232 \u67e5\u8a62\u7de9\u5b58\u6578\u64da\u63d0\u4f9b \u652f\u6301\n\tkeys map&#91;interface{}]*lfuValue\n\t\/\/ \u7de9\u5b58\u6dd8\u6c70\u7b97\u6cd5\u4f7f\u7528 \u4f7f\u7528\u6700\u5c0f\u5806\u6bcf\u6b21\u6dd8\u6c70 \u71b1\u5ea6\u6700\u4f4e\u7684\u5143\u7d20\n\thot *lfuHeap\n}\n\n\/\/ \u56e0\u7232golang\u6c92\u6709\u69cb\u9020\u51fd\u6578 \u63d0\u4f9b\u4e00\u500b New \u51fd\u6578 \u5275\u5efa\u7de9\u5b58\nfunc NewLFU(capacity int) *LFU {\n\tif capacity &lt; 1 {\n\t\tpanic(`capacity must &gt; 0`)\n\t}\n\treturn &amp;LFU{\n\t\tcapacity: capacity,\n\t\tkeys:     make(map&#91;interface{}]*lfuValue, capacity),\n\t\thot:      newLFUHeap(capacity),\n\t}\n}\n\nfunc (c *LFU) Delete(key interface{}) {\n\tv, exists := c.keys&#91;key]\n\tif !exists {\n\t\t\/\/ \u7de9\u5b58\u4e0d\u5b58\u5728 \u76f4\u63a5\u8fd4\u56de\u5373\u53ef\n\t\treturn\n\t}\n\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5f9e Map \u548c Hot \u522a\u9664\u4e4b\n\tdelete(c.keys, key)\n\tc.hot.Remove(v.Index)\n}\n\nfunc (c *LFU) Get(key interface{}) (value interface{}, exists bool) {\n\tv, exists := c.keys&#91;key]\n\tif !exists {\n\t\treturn\n\t}\n\t\/\/ \u7de9\u5b58\u5b58\u5728 \u5c07\u7de9\u5b58\u8a2d\u7f6e\u7d66\u8fd4\u56de\u503c\n\tvalue = v.Value\n\n\t\/\/ \u589e\u52a0\u71b1\u5ea6 \u4e26\u4e14\u91cd\u65b0\u6392\u5e8f\n\tv.Hot++\n\tc.hot.Fix(v.Index) \/\/ \u6700\u5c0f\u5806\u53ea\u9700\u8981\u8abf\u6574\u4e00\u4e0b\u5806\u7d50\u69cb\u5373\u53ef\n\treturn\n}\n\nfunc (c *LFU) Put(key, value interface{}) {\n\tv, exists := c.keys&#91;key]\n\tif exists { \/\/ \u7de9\u5b58\u5b58\u5728 \u66f4\u65b0\u503c \u71b1\u5ea6 \u4e26\u4e14\u91cd\u65b0\u6392\u5e8f\n\t\tv.Hot++\n\t\tv.Value = value\n\t\tc.hot.Fix(v.Index) \/\/ \u6700\u5c0f\u5806\u53ea\u9700\u8981\u8abf\u6574\u4e00\u4e0b\u5806\u7d50\u69cb\u5373\u53ef\n\t\treturn\n\t}\n\t\/\/ \u4e0d\u5b58\u5728\u9996\u5148\u5224\u65b7\u7de9\u5b58\u662f\u5426\u5df2\u6eff\n\tif len(c.keys) == c.capacity {\n\t\t\/\/ \u7de9\u5b58\u5df2\u6eff \u522a\u9664\u71b1\u5ea6\u6700\u5c0f\u7684\u5143\u7d20\n\t\tv := c.hot.Remove(0)\n\t\tdelete(c.keys, v.Key)\n\t}\n\n\t\/\/ \u5c07\u65b0\u7de9\u5b58\u5167\u5bb9\u52a0\u5165\n\tv = &amp;lfuValue{\n\t\tKey:   key,\n\t\tValue: value,\n\t\tHot:   1,\n\t}\n\tc.hot.Push(v)\n\tc.keys&#91;key] = v\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">LFU \u7b97\u6cd5\u7684\u554f\u984c<\/h2>\n\n\n\n<p>LFU \u5f88\u597d\u7684\u89e3\u6c7a\u4e86 FIFO \u71b1\u9ede\u6578\u64da\u5728\u7de9\u5b58\u4e2d\u7684\u6b0a\u91cd\u554f\u984c\u4f46\u540c\u6642\u5f15\u5165\u4e86\u65b0\u7684\u554f\u984c<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>\u6dd8\u6c70\u7b97\u6cd5\u9700\u8981\u4f9d\u64da\u71b1\u5ea6\u6392\u5e8f\uff0c\u7576\u7de9\u5b58\u5927\u91cf\u6578\u64da\u5f8c\u6bcf\u7b46\u7de9\u5b58\u71b1\u5ea6\u767c\u751f\u8b8a\u5316\u90fd\u9700\u8981\u8abf\u6574\u9806\u5e8f\u9019\u53ef\u80fd\u6703\u6d88\u8017\u904e\u591a\u7684\u8cc7\u6e90<\/li><li>\u4e00\u4efd\u6578\u64da\u71b1\u5ea6\u5f88\u9ad8\u5f8c\u5f88\u96e3\u88ab\u6dd8\u6c70\uff0c\u5373\u4f7f\u5b83\u5df2\u7d93\u8b8a\u5f97\u51b7\u9580(\u4f8b\u5982\u4eca\u5929\u672c\u55b5\u767c\u4f48\u4e86\u4e00\u7bc7\u6709\u8da3\u7684\u65b0\u805eA\uff0c\u5b83\u4e00\u4e0b\u5b50\u71b1\u5ea6\u885d\u5230\u5f88\u9ad8\uff0c\u56e0\u7232\u5927\u5bb6\u90fd\u611f\u8208\u8da3\u4e0d\u65b7\u8a2a\u554f\u5b83\uff0c\u4f46\u7b49\u904e\u4e86\u4e00\u500b\u6708\u5f8c\u6c92\u6709\u767c\u751f\u6709\u8da3\u7684\u4e8b\u60c5\u6240\u4ee5\u6c92\u6709\u767c\u5e03\u7206\u70b8\u6027\u7684\u65b0\u805e\u4ee5\u81f4\u65bc\u9019\u500b\u6708\u4f86\u7684\u65b0\u805e\u90fd\u6c92\u6709\u71b1\u5ea6\u8d85\u904eA\u7684\u6240\u4ee5\u5373\u6642\u73fe\u5728\u6c92\u4eba\u770b\u65b0\u805eA\u4e86\uff0c\u4f46\u5b83\u537b\u4f9d\u820a\u5014\u5f37\u7684\u5f85\u5728\u7de9\u5b58\u4e2d\u6d6a\u8cbb\u8005\u8cc7\u6e90)<\/li><\/ul>\n\n\n\n<p>\u9451\u65bc\u4e0a\u8ff0\u554f\u984c\uff0c\u66f4\u5e38\u4f7f\u7528\u7684\u7de9\u5b58\u7b97\u6cd5\u662f LRU\uff0cLRU \u4f7f\u7528\u66f4\u52a0\u7c21\u55ae\u6709\u6548\u7684\u65b9\u5f0f\u6dd8\u6c70\u6578\u64da\uff0c\u672c\u55b5\u5c07\u5728\u4e0b\u7bc7\u6587\u7ae0\u9032\u884c\u8a0e\u8ad6\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>lfu \u7de9\u5b58\u7b97\u6cd5 \u4ecb\u7d39 \u4ee5\u53ca golang \u5be6\u73fe\u793a\u4f8b<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[11,14,2,13],"tags":[21,12,17],"class_list":["post-100","post","type-post","status-publish","format-standard","hentry","category-golang","category-re0-cache","category-code","category-algorithm","tag-cache","tag-golang","tag-lfu"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/100","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=100"}],"version-history":[{"count":13,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/100\/revisions"}],"predecessor-version":[{"id":118,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/100\/revisions\/118"}],"wp:attachment":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=100"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=100"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=100"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}