如何设计最近使用的缓存?
如何设计最近使用的缓存?
假设您访问过一些项目。你需要设计一个数据结构来保存 这些物品。每个项目都与最近访问的时间相关联。
每次访问一个项目时,请在数据结构中检查它。如果该项目已在缓存中,则更新其访问时间。否则,将其插入缓存中。缓存大小是固定的,如果已满,则删除最旧的项。
我的解决方案:
使用地图<项目,visitTime >
初始化:用f(visitTime)对地图进行降序排序。 O(nlg n)
如果访问了某个项目,则使用 O(lg n) 在地图中搜索它。
如果已经在地图中,则更新时间 O(1)。对地图进行排序 O(lg n).
如果没有,则插入到map中,然后排序。 O(lg n)
如果地图大小 >固定大小,删除最后一个元素 O(1)。
另一种解决方案:
使用哈希表<项目 , 访问时间 >
排序 O(n lgn)。
如果访问了某个项目,则在表中搜索它的时间复杂度为 O(1)。
如果已经在表中,则更新时间O(1)。对表格进行排序 O(nlgn)。
如果没有,则插入表中,然后排序。 O(n lg n)
如果表大小 >固定大小,删除最后一个元素 O(1)。
有更好的解决方案吗?在) ?
How to design a latest recently used cache?
Suppose that you have visited some items. You need to design a data structure to hold
these items. Each item is associated with the latest visited time.
Each time when you visit an item, check it in the data structure. If the item has been in the cache, update its visit time. Otherwise, insert it into the cache. The cache size is fixed, if it is full, delete the oldest item.
My solution:
Use a map < item, visitTime >
Initaliztion: Sort the map with f(visitTime) with descending order.
O(nlg n)If an item is visited, search it in the map with O(lg n).
If it has been in the map, update the time O(1). Sort the map O(lg
n).If not, insert it into map and then sort. O(lg n)
If map size > fixed size, delet the last element O(1).
Another solution:
Use hashtable < item , visitTime >
Sort it O(n lgn).
If an item is visited, search it in the talbe with O(1).
If it has been in the table , update the time O(1). Sort the table
O(n lg n).If not, insert it into table and then sort. O(n lg n)
If table size > fixed size, delet the last element O(1).
Are there better solutions ? O(n) ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您使用双向链表,您将获得 O(1) 插入(搜索后)、O(1) 删除、O(n) 搜索。
假设你在前面插入新项:
如果缓存未满,就添加到前面(O(1))。
如果需要更新一个项目,找到它(O(n)),将其从链表中删除(O(1)),然后添加到前面(O(1))。
如果需要删除最旧的元素来插入新元素,请删除末尾元素(O(1)),然后插入到前面(O(1))[注意:在这种情况下,您需要先搜索列表才能看到如果该项目尚未在缓存中,则 O(n)]。
链接列表也可以为您提供相同的时间,因为搜索会将您留在最后一个元素。
If you use a Doubly Linked List, you'll get O(1) insertion (after search), O(1) deletion, O(n) search.
Assuming you insert new items in the front:
If the cache is not full, just add to the front (O(1)).
If you need to update an item, find it (O(n)), remove it from the linked list (O(1)), then add to the front (O(1)).
If you need to delete the oldest to insert a new item, delete the end element (O(1)), and insert to the front (O(1)) [note: you need to search the list first in this case to see if the item is not already in the cache, so O(n)].
A Linked List can also give you the same time, since the search will leave you at the last element.
Python 的 LRU 缓存 具有 O(1) 的插入、删除和删除操作搜索。它的设计使用双向链接的条目列表(从最旧到最新排列)和哈希表来定位特定链接。
这是一个简化(但快速)的版本,由非常基本的 Python 代码组成,不到 40 行。将 Python 的解决方案翻译成 C++ 应该不难:
Python's LRU cache has O(1) insertion, deletion, and search. Its design uses a doubly-linked list of entries (arranged oldest-to-newest) and a hash table to locate a particular link.
Here's a simplified (but fast) version in under 40 lines of very basic Python. It shouldn't be hard to translate Python's solution into C++:
您可以使用 Java 中的 java.util 来完成此操作.LinkedHashSet。它是一个哈希表,加上一个链接列表,保留项目插入的顺序。如果密钥分散效果良好,您应该获得(预期的)恒定时间的查找、插入和删除。
您可能还想查看 WeakHashMap 其中实现了一种可以对元素进行垃圾收集的自动化机制。
You can do it in Java with the java.util.LinkedHashSet. It is a hash table coupled with a linked list which preserves the order in which the items were inserted. You should get (expected) constant time look-ups, insertions and removals if key dispersal works well.
You may also want to look at WeakHashMap which implements an automated mechanism where elements can be garbage collected.
使用共享相同数据的两个集合。有一个哈希表和一个列表。使用哈希表来验证项目是否存在,并在列表中查找它(哈希映射的值为列表迭代器)。使用列表来维护项目之间的顺序。同步两个集合(从列表中删除项目时,从哈希表中删除相应的项目)。列表迭代器必须确保当您在列表中重新定位项目时它不会更改。
编辑: std::list 迭代器在元素的添加和删除过程中都有效,前提是不删除迭代器引用的元素。请参阅 Wikipedia 中容量和分配部分的最后几行。
Use two collections that share the same data. Have one hashtable and one list. Use hashtable to verify if item exists, and to find it in the list (value of hash map is list iterator). Use list to maintain order between items. Synchronize two collections (when removing item from the list, remove corresponding item from hashtable). List iterator must be such that it does not change when you relocate the item within the list.
Edit: std::list iterator is valid throughout addition and deletion of elements, provided that the very element iterator is referencing to is not removed. See last lines in the section Capacity and Allocation in Wikipedia.
您实际上不必对容器进行分类。只需将项目添加到地图或矢量中,然后线性遍历即可找到所需的项目(或最旧的项目)。
那么它将是
O(n)
。You don't really have to sort the container. Just add the items to the map or vector, and go over it linearly to find the needed item (or the oldest item).
Then it will be
O(n)
.看看 boost::multi_index。它显示的示例之一是 MRU 列表。
Have a look at boost::multi_index. One of the examples that it shows is an MRU List.