【问题标题】:optimizing searching through memory优化内存搜索
【发布时间】:2014-11-20 20:26:20
【问题描述】:
我有 4096 个项目的多个实例。我需要定期搜索并找到一个项目,我想对其进行优化。由于并非所有 4096 项都可以使用,我认为,加快速度的一种方法是使用链表而不是数组。每当我必须搜索一个项目时,一旦找到它,我就会将它放在列表的顶部,这样下次它出现时,我只需要做最少的搜索(循环)工作。这听起来对吗?
EDIT1
我不认为二叉搜索树的想法真的是我可以使用的,因为我已经订购了数据,就像一个数组,即前一个节点之后的每个节点都更大,这违背了目的,不是吗?
我试图解决我的缓存问题并想出了这样的事情:
pending edit
但我得到的输出表明它不像我希望的那样工作:
关于如何改进这一点有什么建议吗?
【问题讨论】:
标签:
arrays
performance
loops
optimization
linked-list
【解决方案2】:
在最坏的情况下,除非您像 Brett 建议的那样对数组或列表进行排序,否则您的搜索仍然是 O(N)。因此,使用排序列表会增加插入的复杂性(插入有序),但搜索速度会快得多。您的建议几乎就像“缓存”。如果不知道在短期内再次搜索找到的项目的频率,我们很难说这会有多大用处。显然,缓存有好处,这就是为什么我们在内存中拥有整个 L1、L2、L3 架构的原因。但它是否对你有用还不确定。
【解决方案4】:
回复 Edit1:
我认为如果您的数据元素不大,例如只有几个字节甚至几十个字节,则可以将其中的 4096 个放入内存中。在这种情况下,您需要的是一个哈希表。在 C++ 中,您使用 unordered_map。例如,您可以定义unorderedmap<int, ptr_to_your_node_type>,如果您的键类型为int,则可以获取O(1) 中的元素。
如果你能很好地设计你的哈希,最快的搜索可能是O(1),最坏的情况可能是O(n)。如果这些项目很大并且无法放入内存中,您可以使用所谓的最近最少使用缓存algorithm 来节省内存。
LRU 缓存的示例代码
template <typename K>
class Key_Age{
list<K> key_list;
unordered_map<K, typename list<K> :: iterator> key_pos;
public:
void access(K key){
key_list.erase(key_pos[key]);
insert_new(key);
}
void insert_new(K key){
key_list.push_back(key);
key_pos[key] = --key_list.end();
}
K pop_oldest(){
K t = key_list.front();
key_list.pop_front();
return t;
}
};
class LRU_Cache{
int capacity;
Key_Age<int> key_age;
unordered_map<int, int> lru_cache;
public:
LRU_Cache(int capacity): capacity(capacity) {
}
int get(int key) {
if (lru_cache.find(key) != lru_cache.end()) {
key_age.access(key);
return lru_cache[key];
}
return -1;
}
void set(int key, int value) {
if (lru_cache.count(key) < 1) {
if (lru_cache.size() == capacity) {
int oldest_key = key_age.pop_oldest();
lru_cache.erase(oldest_key);
}
key_age.insert_new(key);
lru_cache[key] = value;
return;
}
key_age.access(key);
lru_cache[key] = value;
}
};