算法練習--LRU緩存機制__HashMap+鏈表

題目:

運用你所掌握的數據結構,設計和實現一個  LRU (最近最少使用) 緩存機制。它應該支持以下操作: 獲取數據 get 和 寫入數據 put 。

獲取數據 get(key) - 如果關鍵字 (key) 存在於緩存中,則獲取關鍵字的值(總是正數),否則返回 -1。
寫入數據 put(key, value) - 如果關鍵字已經存在,則變更其數據值;如果關鍵字不存在,則插入該組「關鍵字/值」。當緩存容量達到上限時,它應該在寫入新數據之前刪除最久未使用的數據值,從而爲新的數據值留出空間。

示例:

LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 該操作會使得關鍵字 2 作廢
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 該操作會使得關鍵字 1 作廢
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

個人思路:

LRU 緩存機制可以通過哈希表輔以雙向鏈表實現,我們用一個哈希表和一個雙向鏈表維護所有在緩存中的鍵值對。

雙向鏈表按照被使用的順序存儲了這些鍵值對,靠近頭部的鍵值對是最久未使用的,而靠近尾部的鍵值對是最近使用的。

哈希表即爲普通的哈希映射(HashMap),通過緩存數據的鍵映射到其在雙向鏈表中的位置

這樣以來,我們首先使用哈希表進行定位,找出緩存項在雙向鏈表中的位置,隨後將其移動到雙向鏈表的頭部,即可在 O(1)的時間內完成 get 或者 put 操作。

代碼:

class Tree{
    int val;
    int key;
    Tree pre;
    Tree next;
    Tree(int key,int val){
        this.key=key;
        this.val=val;
    }
}
class LRUCache {
    int capacity;
    HashMap<Integer,Tree> map=new HashMap();
    Tree head;
    Tree end;

    public LRUCache(int capacity) {
        this.capacity=capacity;

        head=new Tree(0,0);
        end=new Tree(100,100);
        head.next=end;
        end.pre=head;
    }
    
    public int get(int key) {
        if(!map.containsKey(key)){
            return -1;
        }
        Tree curtree=map.get(key);
        int re=curtree.val;

        curtree.pre.next=curtree.next;
        curtree.next.pre=curtree.pre;

        curtree.next=end;
        curtree.pre=end.pre;
        end.pre.next=curtree;
        end.pre=curtree;
        return re;
    }
    
    public void put(int key, int value) {
        if(map.containsKey(key)){
            Tree curtree=map.get(key);

            curtree.pre.next=curtree.next;
            curtree.next.pre=curtree.pre;

            curtree.next=null;
            curtree.pre=null;

            Tree new_curtree=new Tree(key,value);
            new_curtree.next=end;
            new_curtree.pre=end.pre;
            end.pre.next=new_curtree;
            end.pre=new_curtree;

            map.put(key,new_curtree);
        }else{
            Tree new_curtree=new Tree(key,value);
            new_curtree.next=end;
            new_curtree.pre=end.pre;
            end.pre.next=new_curtree;
            end.pre=new_curtree;

            map.put(key,new_curtree);

            if(map.size()>capacity){
                Tree dele_tree=head.next;

                int dele_key=dele_tree.key; 
                map.remove(dele_key);

                head.next=dele_tree.next;
                dele_tree.pre=null;
                dele_tree.next=null;
                head.next.pre=head;

            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章