LRU缓存实现

本着自己实操的原则..手撸了一遍算法4上一道LRU缓存的题,没用java自带的那坨东西,手写了一遍LRU要用到Hash散列表,双向队列,然而并没有看很懂书上写的用符号表存链表元素位置是干啥的。。这坨代码我自己都不想看了,太丑了。



/**
 * Created by eminem on 16-11-29.
 * <p>
 * Created by eminem on 16-11-29.
 * 双向链表
 * isEmpty()判断是否为空
 * size() 元素数量
 * void pushleft() pushRight() 从左右添加元素
 * Item popLeft popRight() 从左右删除元素
 * show() 打印元素
 **/

public class LRU<Item> {

    /**
     * 0.0
     **/

    LRU.queue fuck;
    LRU.sanlie shit;


    private class Node {
        Item item;
        Node front;
        Node next;
    }

    private Node first;
    private Node last;

    //双向队列里的
    private int N=0;


    //散列表的链表数量
    private int M = 997;
    private iSequentialSearchST<String, Integer>[] st;


    /**
     * LRU构造器
     **/
    public LRU() {

        st = (iSequentialSearchST<String, Integer>[]) new iSequentialSearchST[M];
        for (int i = 0; i < M; i++) {
            st[i] = new iSequentialSearchST();
        }

        /**
         * fuck:queue
         * shit:sanlie
         **/

        fuck = this.new queue();
        shit = this.new sanlie();


    }


    /**
     * 队列
     **/
    class queue {
        private Node first;
        private Node last;

        public boolean isEmpty() {
            return N == 0;
        }

        //当next为null时不知道null.item是不是会出错
        public Item delete(Item item) {
            Node x = first;
            if (item.equals(x.item)) {
                return x.item;
            }
            Item it;
            for (; x != null; x = x.next) {
                if (item.equals(x.item)) {
                    it = x.item;
                    if (x.next == null) {
                        x.front.next = null;
                        fuck.pushLeft(item);
                        N--;

                        return it;
                    }
                    x.front.next = x.next;
                    x.next.front = x.front;

                    fuck.pushLeft(item);
                    N--;
                    return it;
                }
            }
            return null;
        }

        public int size() {
            return N;
        }

        public void pushLeft(Item item) {
            Node oldfirst = first;
            first = new Node();
            first.item = item;
            if (isEmpty()) {
                last = first;
                first.next = null;
            } else {
                oldfirst.front = first;
                first.next = oldfirst;
            }
            N++;
        }

        public void pushRight(Item item) {
            Node oldlast = last;
            last = new Node();
            last.next = null;
            last.item = item;
            if (isEmpty()) {
                first = last;
                last.front = null;
            } else {
                last.front = oldlast;
                oldlast.next = last;
            }
            N++;
        }

        public Item popLeft() {
            if (isEmpty()) {
                last = null;
                first = null;
                return null;
            }
            Item item = first.item;
            first = first.next;


            //假设弹出操作之后链表里还有元素,那么把first的front设置为null
            //如果没有元素了,那么正好,这几行代码也不用执行了,全都等于null了
            if (first != null) {
                first.front = null;
            }
            N--;
            return item;
        }

        public Item popRight() {
            if (isEmpty()) {
                first = null;
                last = null;
                return null;
            }

            Item item = last.item;
            last = last.front;
            if (last != null) {
                last.next = null;
            }
            N--;
            return item;
        }

        public void show() {
            for (Node x = first; x != null; System.out.println(x.item), x = x.next) ;
        }
    }
    /**队列**/


    /**
     * 散列表
     **/
    class sanlie {
        private int hash(String key) {
            return (key.hashCode() & 0x7fffffff) % M;
        }

        private Integer get(String key) {
            return st[hash(key)].get(key);
        }

        private void put(String key, Integer val) {
            st[hash(key)].put(key, val);
        }

        private Integer delete(String key) {
            return st[hash(key)].delete(key);
        }


        private boolean contains(String key) {
            int fuck = hash(key);
            return st[fuck].contains(key);
        }
    }
    /**散列表**/


    /**LRU的方法**/
    /**
     * 访问方法
     * 当调用visit方法时,首先检查散列表有没有该元素,
     * <p>
     * A:若[有]该元素,
     * 1.把他从链表删除并插入到链表开头,
     * 2.改变他在散列表中的内容
     * <p>
     * B:若[没有]该元素,
     * 1.把该元素直接插入到链表开头
     * 2.在散列表中加入该元素,并把他的位置写为最新的那个位置
     **/
    public void visit(String key) {
        boolean judge = shit.contains(key);

        //B:
        if (!judge) {
            fuck.pushLeft(key);
            shit.put(key, 0);
        } else if (judge) {
            fuck.delete(key);
        }
    }

    public Item delete() {

        return (Item) fuck.popRight();
    }

    /**LRU的方法**/


}

class iSequentialSearchST<String, Integer> {
    private Node first;

    private class Node {
        String Key;
        Integer val;
        Node next;

        public Node(String key, Integer val, Node next) {
            this.Key = key;
            this.val = val;
            this.next = next;
        }
    }


    protected boolean contains(String key) {
        for (Node x = first; x != null; x = x.next) {
            if (key.equals(x.Key)) {
                return true;
            }
        }
        return false;
    }


    protected Integer get(String key) {

        for (Node x = first; x != null; x = x.next) {
            if (key.equals(x.Key)) {
                return x.val;
            }
        }
        System.out.println("get:Can't find the key" + "=" + "\"" + key + "\"");
        return null;
    }


    /**
     * put方法真的精巧
     * 每次都把新节点插在链表头,把first设置为一个新Node,next设置为刚才的first
     * first = new Node(key, val, first);
     **/
    protected void put(String key, Integer val) {
        if (first == null) {
            first = new Node(key, val, first);
            return;
        } else {
            for (Node x = first; x != null; x = x.next) {
                if (key.equals(x.Key)) {
                    x.val = val;
                    return;
                }
            }

            first = new Node(key, val, first);
        }
    }

    protected Integer delete(String key) {
        //如果这条链表本身就是空的
        if (first == null) {
            System.out.println("delete:Can't find the key" + "=" + "\"" + key + "\"");
            return null;
        }

        Node x = first;
        Node y = x;

        //如果该条链表不是空的那就让这两个指针一前一后走到合适的位置
        while (!key.equals(x.Key)) {
            y = x;
            x = x.next;
            if (x == null) {
                System.out.println("delete:Can't find the key" + "=" + "\"" + key + "\"");
                return null;
            }
        }


        Integer fuck = x.val;

        //处理不同位置的x
        if (x == first) {
            first = null;
        } else {
            y.next = x.next;
        }

        return fuck;

    }
}

猜你喜欢

转载自blog.csdn.net/u010742342/article/details/53408241