Tuesday, November 25, 2014

LRU Cache -- Java


public class LRUCache {
    class Node{
        int key;
        int value;
        Node prev;
        Node next;
     
        public Node(int k, int v){
            key = k;
            value = v;
            prev = null;
            next = null;
        }
        public void setValue(int v){
            value = v;
        }
    }
 
 
    int cap;
    HashMap<Integer,Node> hmap;
    Node head;
    Node tail;
 
    public LRUCache(int capacity) {
        if(capacity<0){
            capacity = 1;
        }
        cap = capacity;
        hmap = new HashMap<Integer, Node>();
        head = null;
        tail = null;
    }
 
    public int get(int key) {
        if(hmap.containsKey(key)){
            if(hmap.size()>1){
                dragKeyNode(hmap.get(key));                   //lru
            }
            return hmap.get(key).value;
        }
        else return -1;
    }
 
    public void set(int key, int value) {
        if(hmap.containsKey(key)){
            dragKeyNode(hmap.get(key));                       //lru
            hmap.get(key).setValue(value);
        }
        else{      
                 //to insert a new Node to the doubly linkedin list.
            Node insertNode = new Node(key,value);
         
            if(hmap.size() < cap){                                     //!important judge.
                attachKeyNode(insertNode);
            }
            else{                                                                 // cur size >=cap
                detachKeyNode();
                attachKeyNode(insertNode);
            }
            hmap.put(key,insertNode);          
        }
        return;
    }
 
   //drag an existed node from original inner pos in doubly linkedlist to the head new pos.

    public void dragKeyNode(Node p){          
        if(p==head)return;                                    //if p==head, nothing needed to do.
     
        Node pprev = p.prev;
        Node pnext = p.next;
     
        pprev.next = pnext;
        if(pnext!=null){
            pnext.prev = pprev;
        }
        else{                                                          //if p is currently tail node, modify tail!
            tail = pprev;
        }
        p.prev = null;
        p.next = null;
        attachKeyNode(p);    
        return;
    }
 
 
    public void attachKeyNode(Node p){
        if(head == null && tail == null){
            head = p;
            tail = p;
        }
        else{                                
            p.next = head;
            head.prev = p;
            head = p;
        }
        return;
    }
 
    public void detachKeyNode(){                  //cut off tail node.
        if(hmap.size() < 1)return;
     
        int key = tail.key;
        hmap.remove(key);                                 //!important, also need to delete tail node in hashmap.
     
        if(hmap.size()==0){
            head = null;
            tail = null;
        }
        else{
            Node pprev = tail.prev;
            pprev.next = null;
            tail.prev = null;
            tail = pprev;
        }
        return;
    }
}

No comments:

Post a Comment