Java实现双端队列

/**
 * @Classname MyDeque
 * @Description 使用循环数组实现双端队列
 * @Date 2022-7-8 19:14
 * @Created by Yang Yi-zhou
 */
public class MyDeque<E> {
    //默认容量
    private static final int DEFAULT_CAPACITY = 8;
    //最大容量
    private static final int MAX_CAPACITY = Integer.MAX_VALUE;

    //存储数组
    private Object[] elements;
    //队列头
    private int head;
    //队列尾
    private int tail;
    //队列元素个数
    private int size;

    //无参构造器,使用默认容量初始化
    public MyDeque() {
        //初始化
        this.elements = new Object[DEFAULT_CAPACITY];
        this.head = 0;
        this.tail = 0;
        this.size = 0;
    }

    //指定容量大小的构造器
    public MyDeque(int capacity) {
        //合法性检查
        if (capacity < 0 || capacity > MAX_CAPACITY) {
            throw new IllegalArgumentException("parameter is illegal");
        }
        //使用给定的容量初始化
        this.elements = new Object[capacity];
        this.head = 0;
        this.tail = 0;
        this.size = 0;
    }

    /**
     * 在双端队列的开头添加指定的元素。
     *
     * @param element 要添加的元素
     * @return 是否添加成功
     */
    public boolean offerFirst(E element) {
        //判断队列是否满了
        if (size == elements.length) {
            doubleCapacity();
        }
        //如果队列为空
        if (isEmpty()) {
            elements[head] = element;
        } else {
            //添加元素到队列头,head左移
            elements[getRealIndex(head - 1)] = element;
            //更新队列状态
            head = getRealIndex(head - 1);
        }
        size++;
        return true;
    }

    /**
     * 在双端队列的尾部添加指定的元素。
     *
     * @param element 要添加的元素
     * @return 是否添加成功
     */
    public boolean offerLast(E element) {
        //判断队列是否满了
        if (size == elements.length) {
            doubleCapacity();
        }
        //如果队列为空
        if (isEmpty()) {
            elements[tail] = element;
        } else {
            //添加元素到队列尾,tail右移
            elements[getRealIndex(tail + 1)] = element;
            //更新队列状态
            tail = getRealIndex(tail + 1);
        }
        size++;
        return true;
    }


    /**
     * 返回并删除双端队列的队头元素。如果双端队列为空,则返回null。
     *
     * @return
     */
    public E pollFirst() {
        //判断队列是否为空
        if (isEmpty()) return null;
        //删除除队列的第一个元素
        E removedElement = (E) elements[head];
        elements[head] = null;
        //head右移
        head = getRealIndex(head + 1);
        size--;
        return removedElement;
    }

    /**
     * 返回并删除双端队列的队尾元素。如果双端队列为空,则返回null。
     *
     * @return
     */
    public E pollLast() {
        //判断队列是否为空
        if (isEmpty()) return null;
        //删除除队列的第一个元素
        E removedElement = (E) elements[tail];
        elements[tail] = null;
        //tail左移
        tail = getRealIndex(tail - 1);
        size--;
        return removedElement;
    }

    /**
     * 返回双端队列的第一个元素。如果双端队列为空,则返回null。
     *
     * @return
     */
    public E peekFirst() {
        if (isEmpty()) return null;
        return (E) elements[head];
    }

    /**
     * 返回双端队列的最后一个元素。如果双端队列为空,则返回null。
     *
     * @return
     */
    public E peekLast() {
        if (isEmpty()) return null;
        return (E) elements[tail];
    }


    /**
     * 判断队列是否为空
     *
     * @return true:为空 false:不为空
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 扩增队列容量
     */
    public void doubleCapacity() {
        //检查队列是否已达到上限
        if (elements.length == MAX_CAPACITY) throw new RuntimeException("deque is full");
        //新的队列容量为目前的两倍
        int newCapacity = elements.length * 2;
        //检查新容量是否超过最大容量限制
        if (newCapacity > MAX_CAPACITY) newCapacity = MAX_CAPACITY;
        //使用新容量构造一个新的数组
        Object[] newArr = new Object[newCapacity];
        //把元素移动到新的数组中
        for (int i = 0; i < elements.length; i++) {
            newArr[i] = elements[getRealIndex(head + i)];
        }
        //更新队列状态
        head = 0;
        tail = elements.length - 1;
        elements = newArr;
    }

    /**
     * 获取真实下标
     *
     * @param logicIndex 逻辑下标
     * @return 真实下标
     */
    private int getRealIndex(int logicIndex) {
        int innerArrayLength = elements.length;
        //逻辑下标小于0
        if (logicIndex < 0) {
            //加上当前数组的长度
            logicIndex += innerArrayLength;
        }
        //逻辑下标大于等于数组长度
        if (logicIndex >= innerArrayLength) {
            //减去当前数组的长度
            logicIndex -= innerArrayLength;
        }
        //返回真实下标
        return logicIndex;
    }

    /**
     * 打印deque
     */
    public void printDeque() {
        for (int i = 0; i < elements.length; i++) {
            if (elements[getRealIndex(head + i)] == null) break;
            System.out.print(elements[getRealIndex(head + i)].toString());
            System.out.print("-->");
        }
        System.out.println("\b\b\b");
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected int size;//队列中元素的数目 //构造函数 public Deque_DLNode() { header = new DLNode(); trailer = new DLNode(); header.setNext(trailer); trailer.setPrev(header); size = 0; } //返回队列中元素数目 public int getSize() { return size; } //判断队列是否为空 public boolean isEmpty() { return (0 == size) ? true : false; } //取首元素(但不删除) public Object first() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return header.getNext().getElem(); } //取末元素(但不删除) public Object last() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return trailer.getPrev().getElem(); } //在队列前端插入新节点 public void insertFirst(Object obj) { DLNode second = header.getNext(); DLNode first = new DLNode(obj, header, second); second.setPrev(first); header.setNext(first); size++; } //在队列后端插入新节点 public void insertLast(Object obj) { DLNode second = trailer.getPrev(); DLNode first = new DLNode(obj, second, trailer); second.setNext(first); trailer.setPrev(first); size++; } //删除首节点 public Object removeFirst() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = header.getNext(); DLNode second = first.getNext(); Object obj = first.getElem(); header.setNext(second); second.setPrev(header); size--; return(obj); } //删除末节点 public Object removeLast() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = trailer.getPrev(); DLNode second = first.getPrev(); Object obj = first.getElem(); trailer.setPrev(second); second.setNext(trailer); size--; return(obj); } //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNex
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值