- The data structure is shown in the figure: hash table and doubly linked list
- Since the search time is complex to o(1), only a hash table can be used.
- Since the time complexity of insert, delete, and move is o(1), only a doubly linked list can be used.
The key of the hash table is the value of the node, and the value is a pointer to the position of the doubly linked list. Only the doubly linked list can move or delete the node in o(1) time. In order to simplify some judgments, a dummy node is added to the head and tail.
- Find get(key)
- If there is no such key value in the hash table, return -1
- If so, find a node in the singly linked list through the value of the hash table, move the node to the head of the linked list , and return the node value
- Insert put(key, value)
- If the key value does not exist
- Create a new node in the doubly linked list, and create a key-value pair in the hash table
- Determine whether the number of nodes at this time exceeds the capacity
- If the capacity is exceeded, delete the node at the end of the linked list, delete the corresponding item in the hash table, and update the capacity.
- If the key value exists
- Locate the node through the hash table, modify the value of the node, and insert the node into the header.
- If the key value does not exist
Too difficult (come on!), the precautions are as follows
Not familiar with the operation of hash tables:
- Define the hash table: unordered_map<int, DListNode*> HashMap;
- Determine whether the hash table is empty: if (HashMap.count(key) == 0) return -1;
- Add a new key-value pair to the hash table: HashMap[key] = p;
- Delete the corresponding entry according to the key value of the hash table: HashMap.erase(q->key);
Not familiar with the syntax of C++ constructor
- Use the initialization list to initialize the field. After the colon is the member variable, assign the value directly in the parentheses
- LRUCache(int _capacity) : capacity(_capacity), size(0){middle omitted}
- DListNode() : key(0), value(0), front(nullptr), next(nullptr) {}
- DListNode(int _key, int _value) : key(_key), value(_value), front(nullptr),next(nullptr){}
Incomplete understanding of data structure
- The node of the doubly linked list must store both the key and the value: the value is stored because the get function searches for the value by the key. Although the value of the hash table is a pointer, the double-linked list node pointed to by the pointer should return a value to the user. The key is stored because when the capacity is too large, in addition to removing the end node of the double-linked list, the corresponding entry in the hash table must be removed, and the erase needs to obtain the key value.
I am quite familiar with the various broken link operations of double-linked lists, praise!
struct DListNode {
int key,value;
struct DListNode* front;
struct DListNode* next;
DListNode() : key(0), value(0), front(nullptr), next(nullptr) {}//在结构体中定义构造函数,这是不带参数的
DListNode(int _key, int _value) : key(_key), value(_value), front(nullptr), next(nullptr){}//这是带参数的
};
class LRUCache {
private:
DListNode* head;
DListNode* tail;
int size;
int capacity;
unordered_map<int, DListNode*> HashMap;
public:
LRUCache(int _capacity) : capacity(_capacity), size(0) {//构造函数
head = new DListNode();
tail = new DListNode();
head->next = tail;
tail->front = head;
}
int get(int key) {
if (HashMap.count(key) == 0)return -1;//查找失败返回-1
DListNode* p=HashMap[key];
moveTohead(p);
return p->value;
}
void put(int key,int value) {
if (HashMap.count(key) == 0) {//如果不存在
//创建双链表结点
DListNode* p = new DListNode(key,value);
//插入双链表的表头
insertTohead(p);
//插入hash表
HashMap[key] = p;
++size;
if (size > capacity) {
//如果容量不足,删除表尾
DListNode* q=deleteTail();
//删除哈希表中对应的项
HashMap.erase(q->key);
//防止内存泄漏
delete q;
--size;
}
}
else {
//如果存在
DListNode* p = HashMap[key];
p->value = value;
moveTohead(p);
}
}
DListNode* deleteTail() {
DListNode* p = tail->front;
p->front->next = tail;
tail->front = p->front;
return p;
}
void insertTohead(DListNode* p){
p->front = head;
p->next = head->next;
head->next->front=p;
head->next = p;
}
void moveTohead(DListNode* p) {
p->front->next = p->next;
p->next->front = p->front;
//把p结点取下来
p->front = head;
p->next = head->next;
head->next->front = p;//p结点插入表头
head->next = p;
}
};