LRU Cache [leetcode]

使用双向链表+map,实现O(1)时间内的get和set

需要注意的是:

1. set时更新tail

size为0时更新头部

size为capacity时删除头部并且更新头部

2. get时更新节点到tail的位置,同时如果是节点是头部的话要更新头部

附上代码:

class LRUCache{
    struct Node{
        int key;
        int val;
        Node* next;
        Node* pre;
        
        Node(int k, int v)
        {
            key = k;
            val = v;
            next = pre = NULL;
        }
    };
    
    Node * head;
    Node * tail;
    int size;
    int cap;
    map<int, Node*> keyMap;
public:
    LRUCache(int capacity) {
        head = tail = NULL;
        cap = capacity;
        size = 0;
        keyMap = map<int, Node*>();
    }
    
    ~LRUCache(){
        while (head)
        {
            Node * deleteNode = head;
            head = head->next;
            delete deleteNode;
        }
    }
    
    Node * getNode(int key)
    {
        if (keyMap.find(key) == keyMap.end())
            return NULL;
        Node* foundNode = keyMap[key];
        if (size == 1 || foundNode == tail) return foundNode;
        if (foundNode == head)//size > 1, foundNode->next is not NULL
            head = foundNode->next;
        //remove foundNode from list
        foundNode->next->pre = foundNode->pre;
        if (foundNode->pre) foundNode->pre->next = foundNode->next;
        //update tail
        tail->next = foundNode;
        foundNode->pre = tail;
        tail = tail->next;
        //update foundNode
        foundNode->next = NULL;
        return foundNode;
    }
    
    int get(int key) {
        Node * foundNode = getNode(key);
        if (foundNode)  return foundNode->val;
        else            return -1;
    }
    
    void set(int key, int value) {
        Node * foundNode = getNode(key);//put Node to the front of list
        //if key exists, update value
        if (foundNode)
        {
            foundNode->val = value;
            return;
        }
        //if key not exists, create Node
        Node * newNode = new Node(key, value);
        keyMap[key] = newNode;
        if (size == 0)
            tail = head = newNode;
        else
        {
            tail->next = newNode;
            newNode->pre = tail;
            tail = tail->next;
        }
        size++;
        //check if need delete
        if (size <= cap) return;
        Node * deleteNode = head;
        head = head->next;
        head->pre = NULL;
        keyMap.erase(deleteNode->key);
        delete deleteNode;
        size--;
    }
};



这是我第一次写的时候的代码:

class LRUCache{
public:
	struct Node
	{
		int value;
		int key;
		Node * next;
		Node * pre;
		Node(int v, int k)
		{
			value = v;
			key = k;
			next = pre = 0;
		}
	};
	LRUCache(int capacity) {
		head = 0;
		tail = 0;
		hash = unordered_map<int, Node*>();
		max_cap = capacity;
		cur_cap = 0;
	}
	~LRUCache()
	{
		hash.clear();
		Node* temp;
		while (head)
		{
			temp = head;
			head = head->next;
			delete temp;
		}
	}

	int get(int key) {
		if (hash.find(key) != hash.end())
		{
			Node* cur = hash[key];
			remove(cur);
			push(cur);
			return cur->value;
		}
		return -1;
	}

	void set(int key, int value) {
		if (hash.find(key) != hash.end())
		{
			Node* cur = hash[key];
			remove(cur);
			push(cur);
			cur->value = value;
		}
		else if (cur_cap < max_cap)//没有满
		{
			cur_cap++;
			Node* newNode = new Node(value, key);
			hash[key] = newNode;
			push(newNode);
		}
		else
		{
			Node* newNode = new Node(value, key);
			hash[key] = newNode;
			push(newNode);
			int key = popNode();
			hash.erase(key);
		}
	}
private:
	void remove(Node * n)//将节点从链表里取出,但是不释放空间
	{
		if (n == head)//n的前面没有节点
		{
			head = head->next;
			if (head == 0)//唯一一个节点已经拿走
				head = tail = 0;
			else
				head->pre = 0;
			n->next = 0;
		}
		else if (n == tail)//至少2个节点,否则head == tail == n
		{
			tail = tail->pre;
			tail->next = 0;
			n->pre = 0;
		}
		else
		{
			n->pre->next = n->next;
			n->next->pre = n->pre;
			n->pre = n->next = 0;
		}

	}
	void push(Node * n)//将节点放入尾部
	{
		if (head == 0)//0个节点
		{
			head = tail = n;
		}
		else//至少一个节点
		{
			tail->next = n;
			n->pre = tail;
			tail = n;
		}
	}
	int popNode()//删除最开始的节点
	{
		if (head == 0)//0个节点
			return 0;
		else if (head == tail)//一个节点
		{
			int key = head->key;
			delete head;
			head = tail = 0;
			return key;
		}
		else//至少2个节点
		{
			int key = head->key;
			head = head->next;//head不可能为空
			delete head->pre;
			head->pre = 0;
			return key;
		}
	}
	Node * head;
	Node * tail;
	unordered_map<int, Node*> hash;
	int max_cap;
	int cur_cap;
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值