[Leetcode] -146-LRU caching mechanism-hash table + doubly linked list

 

  • 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.

Too difficult (come on!), the precautions are as follows

Not familiar with the operation of hash tables:

  1. Define the hash table: unordered_map<int, DListNode*> HashMap;
  2. Determine whether the hash table is empty: if (HashMap.count(key) == 0) return -1;
  3. Add a new key-value pair to the hash table: HashMap[key] = p;
  4. 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

  1. Use the initialization list to initialize the field. After the colon is the member variable, assign the value directly in the parentheses
    1. LRUCache(int _capacity) : capacity(_capacity), size(0){middle omitted}
    2. DListNode() : key(0), value(0), front(nullptr), next(nullptr) {}
    3. DListNode(int _key, int _value) : key(_key), value(_value), front(nullptr),next(nullptr){}

Incomplete understanding of data structure

  1. 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;
	}
};

 

Guess you like

Origin blog.csdn.net/qq_39328436/article/details/113730187