leetcode-460. LFU 缓存

leetcode-460. LFU 缓存_第1张图片
总结:哈希表+时间链表+频率链表
哈希表定位到时间节点,时间节点定位到频率节点。
核心:维护key节点hash表,频率链表
不管怎么操作,minfre都要更新,put新插入更新,put更新更新,get更新

维护下面内容

struct TNode;//key对应的节点,内容包括key,value,频率指针,下一个TNode节点指针,上一个TNode节点指针,形成一个按时间排序的=双向链表
struct FNode;//频率节点,内容包括指向下一个频率节点的指针,频率值,TNode的头指针,形成一个频率链表
unordered_map<int,TNode*> memo;//找到对应的节点

leetcode-460. LFU 缓存_第2张图片

class LFUCache {
public:
    struct FNode;
    struct TNode{
        int key_;
        int value_;
        FNode* fre_ptr{NULL};
        TNode* next{NULL};
        TNode* pre{NULL};
        TNode(int key,int value):key_(key),value_(value){}
    };
    struct FNode{
        int fre_;
        FNode* next{NULL};
        TNode* head=new TNode(-1,-1);
        TNode* tail=new TNode(-1,-1); 
        FNode(int fre):fre_(fre){
            head->next=tail;
            tail->pre=head;
        }
    };
    void check(string state,int key){
        cout<<state<<key<<endl;
        FNode * f=frehead->next;
        while(f->fre_!=-1){
            cout<<"fre"<<f->fre_<<":";
            TNode* t=f->head->next;
            while(t->key_!=-1){
                cout<<t->key_;
                t=t->next;
            }
            cout<<endl;
            f=f->next;
        }
        cout<<endl;
    }
    void outTNode(TNode* node){
        node->pre->next=node->next;
        node->next->pre=node->pre;
    }
    void addFre(TNode* node){
        FNode* f=node->fre_ptr;
        if(f->next->fre_==-1){
            FNode* t=new FNode(f->fre_+1);
            t->next=f->next;
            f->next=t;
        }
        f=f->next;
        node->fre_ptr=f;
        node->pre=f->head;
        node->next=f->head->next;
        f->head->next->pre=node;
        f->head->next=node;
    }
    FNode* frehead=new FNode(0);
    FNode* tailhead=new FNode(-1);
    int idle_;
    unordered_map<int,TNode*> memo;
    FNode* minFre;
    LFUCache(int capacity) {
        if(capacity==0) idle_=-1;
        else idle_=capacity;
        frehead->next=tailhead;
        minFre=frehead;
    }
    int get(int key) {
        if(memo.find(key)==memo.end())
         return -1;
        outTNode(memo[key]);
        addFre(memo[key]);
        if(minFre->head->next->key_==-1)
            minFre=minFre->next;
           // check("get",key);
        return memo[key]->value_;
    }
    
    void put(int key, int value) {
        if(idle_==-1)
         return ;
        if(memo.find(key)==memo.end()&&idle_>0){
            idle_--;
            TNode* t=new TNode(key,value);
            t->fre_ptr=frehead;
            memo[key]=t;
            addFre(memo[key]);
            minFre=frehead->next;
        }else if(memo.find(key)==memo.end()&&idle_==0){
            TNode* node=minFre->tail->pre;
            outTNode(node);
            memo.erase(node->key_);
            memo[key]=node;
            node->key_=key;
            node->value_=value;
            node->fre_ptr=frehead;
            addFre(node);
            minFre=frehead->next;
        }else if(memo.find(key)!=memo.end()){
            outTNode(memo[key]);
            memo[key]->value_=value;
            addFre(memo[key]);
            if(minFre->head->next->key_==-1) minFre=minFre->next;   
        }
        //check("put",key);
    }
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache* obj = new LFUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

你可能感兴趣的:(leetcode+算法)