// 1.哈希表
// 2.双向链表
class LRUCache
{
public:
// 1.双向链表的结点
struct Node
{
int key, val;
// 指向下一个的前驱和后继结点
Node *prev, *next;
// 初始化列表
Node(int k, int v)
: key(k), val(v), prev(nullptr), next(nullptr)
{
}
};
// 2.创建哈希表
// 存储有没有结点这个指针的位置
unordered_map<int, Node *> mp;
// 哨兵,操作边界,链表是否为空的情况
// 要对链表进行插入删除
Node *L, *R;
// 3.容量
int n;
LRUCache(int capacity)
{
n = capacity;
// 初始化
L = new Node(-1, -1);
R = new Node(-1, -1);
// 把左边的和右边的链表连在一起
L->next = R;
R->prev = L;
}
int get(int key)
{
// 获取
// key在不在哈希表里面,在的话就从哈希表里面拿到node结点
if (mp.count(key))
{
Node *node = mp[key];
remove(node); // 从链表中移除该节点
insert(node->key, node->val); // 刷新 插入到最右边 在链表的最右边插入该节点
return node->val; // 获取到该节点的value
}
else // 节点不存在
{
return -1;
}
}
// 更新操作
void put(int key, int val)
{
if (mp.count(key))
{
Node *node = mp[key];
remove(node);
insert(key, val);
}
else
{ // 不在哈希表,新增一个元素
if (mp.size() == n)
{
// 删掉最左边
Node *node = L->next; // 拿到最左边
remove(node);
insert(key, val);
}
else
{
insert(key, val);
}
}
}
// 4.同时在链表和哈希表中删除某个key
void remove(Node *node)
{
// 移除结点,直接跳过要删除的结点,更改前驱后继指向
// a= b= c
auto pre = node->prev;
auto nxt = node->next;
pre->next = nxt; // a的后继指向c
nxt -> prev = pre; // c的前驱指向a
mp.erase(node->key);
}
void insert(int key,int val)
{
//创建一个结点 a b R
auto node = new Node(key,val);
//先找邻居
auto pre = R ->prev;
auto nxt = R;
pre ->next = node;
node ->next=nxt;
nxt->prev=node;
node ->prev=pre;
//哈希表中存的是key-value,value指向双向链表的结点
mp[key]=node;
}
};
[leetcode146. LRU 缓存]
最新推荐文章于 2024-06-22 22:59:06 发布