• LeetCode: LRU Cache [146]


    【题目】

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

    get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
    set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.


    【题意】

            实现LRU策略

            1. 依据key取value

            2. 插入key-value时,须要删除LRU的item


    【思路】

            维护一个Map记录相应的<key, value>对
            为了模拟key的訪问先后关系,须要维护一个訪问次序列表,越靠后的节点,訪问时间距当前时间越短
    而在insert或者訪问key的时候,须要从列表中找到相应的key,并把它调整到列表为。
    这里遇到两个问题,一个是查找,还有一个是移动到末尾

    假设使用顺序表,查找O(n),移动O(n),在cache规模非常大时时间代价过高
    因此这里使用双向链表来处理


    【代码】

    struct Node{
        int key;
        int val;
        Node*prev;
        Node*next;
        Node(int k, int v): key(k), val(v){
            prev=NULL; next=NULL;
        }
    };
    
    class LRUCache{
    private:
    	Node* head;
    	Node* tail;
    	int capacity;
    	map<int, Node*>cache;
    public:
        LRUCache(int capacity) {
            this->head = NULL;
    		this->tail = NULL;
    		this->capacity = capacity;
        }
    	
    	void move2tail(Node* node){
    		if(node==tail)return;
    		if(node==head){
    			head = node->next;
    			head->prev=NULL;
    			tail->next=node;
    			node->prev=tail;
    			tail=node;
    			tail->next=NULL;
    		}
    		else{
    			node->prev->next = node->next;
    			node->next->prev = node->prev;
    			tail->next=node;
    			node->prev=tail;
    			tail=node;
    			tail->next=NULL;
    		}
    	}
        
        int get(int key) {
            if(this->cache.find(key)==this->cache.end())return -1;
    		move2tail(this->cache[key]);
    		return this->cache[key]->val;
        }
        
        void set(int key, int value) {
            if(this->cache.find(key)==this->cache.end()){//cache中还没有
    			if(this->capacity==0){//cache已经满了
    				//删除头结点
    				this->cache.erase(head->key);
    				head=head->next;
    				if(head)head->prev=NULL;
    				else tail=NULL;
    			}
    			else{//cache还没满
    				this->capacity--;
    			}
    			//加入新节点
    			Node* newNode=new Node(key, value);
    			this->cache[key]=newNode;
    			if(tail){
    				tail->next=newNode;
    				newNode->prev=tail;
    				tail=newNode;
    				tail->next=NULL;
    			}
    			else{
    				head=tail=newNode;
    			}
    		}
    		else{//cache中已经有了
    			this->cache[key]->val = value;
    			move2tail(this->cache[key]);
    		}
        }
    };


  • 相关阅读:
    flume sink两种类型 file_rool 自定义sing com.mycomm.MySink even if there is only one event, the event has to be sent in an array
    为什么引入进程20年后,又引入线程?
    As of Flume 1.4.0, Avro is the default RPC protocol.
    Google Protocol Buffer 的使用和原理
    Log4j 2
    统一日志 统一订单
    网站行为跟踪 Website Activity Tracking Log Aggregation 日志聚合 In comparison to log-centric systems like Scribe or Flume
    Percolator
    友盟吴磊:移动大数据平台的架构、实践与数据增值
    Twitter的RPC框架Finagle简介
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3890809.html
Copyright © 2020-2023  润新知