菜鸟笔记
提升您的技术认知

面试题

实现一个LRU Cache 算法LRU Cache C++三种解法java实现LRU算法及编码实现LRU策略缓存LRU算法常见缓存算法和LRU的c++实现设计循环双端队列(deque)LRU 缓存结构 (c++ 哈希双链表实现)LRU缓存机制删除单链表中的指定节点Linux 内核经典面试题拼多多社招面经:Redis是重点,讲一讲redis的内存模型线程、进程、协程的区别C++经典面试题面试官:我们只想要这样的C++工程师Linux C/C++ 学习路线链表操作汇总C++11的智能指针面试题浏览器中输入url后发生的事情常用的限流算法HTTP协议和HTTPS协议面试题网络编程面试题目总结c++后台面试题目如何实现LRU算法?如何寻找无序数组中的第K大元素?布隆过滤器 - 如何在100个亿URL中快速判断某URL是否存在?如何实现大整数相加?C++面试题及基本知识点总结C++给定出栈序列判定是否合法消息队列面试题要点redis缓存击穿,失效以及热点key解决方案网页在浏览器上的渲染过程几种限流算法lru算法例题C/C++常见面试知识点总结附面试真题----20210529更新引入MQ消息队列的作用及其优缺点MySQL面试篇社招三年后端面试题60道测开面试题,背完直接涨工资二叉树的层序遍历(两种方法实现)Bitmap 海量数据处理字符串倒序输出的五种方法C语言 输入10个数,统计出并输出正数、负数和0的个数字节三面:如何设计一个高并发系统架构,网络 面试36问,DDos攻击原理C++线程池使用 C++11 编写可复用多线程任务池

设计循环双端队列(deque)

阅读 : 2739

队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限的线性表。进行插入操作的端成为队尾,进行删除操作的端称为队头。

双端队列:两端都可以进队和出队的队列

  • 从后端进前端出 或者 从前端进后端出 体现了 先进先出 的特点;
  • 从后端进后端出 或者 从前端进前端出 体现了 先进后出 的特点。

图示:
分别从前端和后端插入节点:

分别从前端和后端删除节点:

实现代码如下:
【注】我用了一个计数器count来统计双端队列中的元素个数,方便判断栈空与栈满。实际上,用链式结构实现循环双端队列,不存在栈满情况,除非内存满了。但题目要求,故加之。

public class MyCircularDeque {
    class node{
        int val;
        node next = null;
        node pre = null;

        node(int v){
            this.val = v;
        }
    }

    node firsthead = null;
    node lasthead = null;
    int capacity;  //链表的总节点容量
    int count;   //链表的当前节点容量

    /** Initialize your data structure here. Set the size of the deque to be k. */
    public MyCircularDeque(int k) {
        this.capacity = k;
        this.count = 0;
    }

    /** Adds an item at the front of Deque. Return true if the operation is successful. */
    //头插法 保持队列的先进先出特性
    public boolean insertFront(int value) {
        if(isFull()){
            return false;
        }
        node nd = new node(value);
        //只要firsthead为空,那么lasthead必定为空
        if(firsthead==null){
            firsthead = nd;
            lasthead = nd;
        }else {
            //只要firsthead不空 lasthead肯定也不空
            nd.next = firsthead;
            firsthead.pre = nd;
            firsthead = nd;
        }
        count++;
        return true;
    }

    /** Adds an item at the rear of Deque. Return true if the operation is successful. */
    public boolean insertLast(int value) {
        if(isFull())
            return false;
        node nd = new node(value);
        if(lasthead==null){
            lasthead = nd;
            firsthead = nd;
        }else {
            nd.pre = lasthead;
            lasthead.next = nd;
            lasthead = nd;
        }
        count++;
        return  true;

    }

    /** Deletes an item from the front of Deque. Return true if the operation is successful. */
    public boolean deleteFront() {
        if(isEmpty())
            return false;
        if(count==1){
            firsthead = null;
            lasthead = null;
        }else {
            firsthead = firsthead.next;
            firsthead.pre = null;
        }
        count--;
        return true;
    }

    /** Deletes an item from the rear of Deque. Return true if the operation is successful. */
    public boolean deleteLast() {
        if (isEmpty())
            return false;
        if (count==1){
            firsthead = null;
            lasthead = null;
        }else {
            lasthead = lasthead.pre;
            lasthead.next = null;
        }
        count --;
        return true;

    }

    /** Get the front item from the deque. */
    public int getFront() {
        if(this.firsthead == null)
            return -1;
        else
            return firsthead.val;
    }

    /** Get the last item from the deque. */
    public int getRear() {
        if(this.lasthead == null)
            return -1;
        else
            return this.lasthead.val;
    }

    /** Checks whether the circular deque is empty or not. */
    public boolean isEmpty() {
        if(this.count == 0)
            return true;
        else
            return false;
    }

    /** Checks whether the circular deque is full or not. */
    public boolean isFull() {
        if(this.count==this.capacity)
            return true;
        else
            return false;
    }
}

另外,还可以了解一下共享栈的结构


用数组实现,数组两端分别为栈底,通过两个栈顶指针进行出入栈操作。栈空与栈满的条件也很好判断。