双端队列
是限定插入和删除操作在表的两端进行的线性表,是一种具有队列和栈的性质的数据结构
双端队列接口的定义
双端队列的大致思想与循环队列一样,无非在队首科添加,在队尾可删除
这是之前所学的一个结构图
ArrayQueue类
package 动态数组;
import 数据接口的实现.Deque;
import 数据接口的实现.Stack;
import java.util.Iterator;
//双端队列
//没有提供可以在任意角标处操作元素的功能
public class ArrayDeque<E> implements Deque<E>, Stack<E> {
private E[] data;
private int front;//队首指针 front ==rear 双端队列为空
private int rear;//队尾指针 (rear+1)%len ==front双端队列满了
private int size;//有效元素的个数
private static int DEFAULT_SIZE =10;
//由用户指定一个容量
public ArrayDeque(int capacity){
data =(E []) new Object[capacity+1];
front=0;
rear=0;
size=0;
}
//默认无参
public ArrayDeque(){
this(DEFAULT_SIZE);
}
@Override
//在Deque的队尾添加一个元素
public void addLast(E element) {
//先判断Deque是否是满的
if(isExpansion()){
resize(data.length*2-1);
}
data[rear] = element;
rear=(rear+1)%data.length;
size++;
}
@Override
//在Deque的队首添加一个元素
public void addFirst(E element) {
//先判断Deque是否是满的
if(isExpansion()){
resize(data.length*2-1);
}
front =((front-1+data.length)%data.length);
data[front]=element;//此时的front已经变了,所以不需要减减了
size++;
}
private void resize(int newLength) {
E [] newData = (E [])new Object[newLength];
int index =0;
for(int i=front;i!=rear;i=(i+1)%data.length){
newData[index++] = data[i];
}
front =0;
rear = index;
data = newData;
}
//是否扩容的函数
private boolean isExpansion(){
return (rear+1)%data.length == front;
}
@Override
//Deque的队首删除一个元素
public E removeFirst() {
if(isEmpty()){
throw new NullPointerException("元素为空");
}
E ret = data[front];
front = (front+1)%data.length;
size--;
//再判断是否要缩容
if(isShrink()){
resize(data.length/2+1);
}
return ret;
}
private boolean isShrink() {
return size ==(data.length-1)/4&& (data.length-1)>DEFAULT_SIZE;
}
@Override
public E removeLast() {
if(isEmpty()){
throw new NullPointerException("元素为空");
}
rear = (rear-1+data.length)%data.length;
E ret = data[rear];
size--;
return ret;
}
@Override
//获取队尾元素
public E getLast() {
return data[(rear-1+data.length)%data.length];
}
@Override
//获取队首元素
public E getFirst() {
return data[front];
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size==0&&front == rear;
}
@Override
public void push(E element) {
//栈,入栈————>front当做栈底,rear当做栈顶,也可以反着来
addLast(element);
}
@Override
public E pop() {
//栈,出栈————>front当做栈底,rear当做栈顶,也可以反着来
return removeLast();
}
@Override
//获取栈顶元素
public E peek() {
//栈,获取栈顶元素————>front当做栈底,rear当做栈顶,也可以反着来
return getLast();
}
@Override
//入队操作,在队尾添加元素。。front队首,rear队尾
public void offer(E element) {
addLast(element);
}
@Override
//出队操作-->removeFirst-->front队首,rear队尾
public E poll() {
return removeFirst();
}
@Override
//队列当中获取队首元素-->front队首,rear队尾
public E element() {
return getFirst();
}
@Override
public void clear() {
data =(E []) new Object[DEFAULT_SIZE+1];
front =0;
rear =0;
size=0;
}
public String toString(){
StringBuilder sb =new StringBuilder(String.format("ArrayDeque:%d/%d[",size,data.length));
if(isEmpty()){
sb.append(']');
}
else{
for(int i=front;i!=rear;i=(i+1)%data.length){
sb.append(data[i]);
if((i+1)%data.length==rear){
sb.append(']');
}
else{
sb.append(',');
}
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return new ArrayDequeIterator();
}
//默认的迭代方向是从front到rear的,也可多从rear到front
class ArrayDequeIterator implements Iterator<E>{
private int cur =front;
@Override
public boolean hasNext() {
return cur!=rear;
}
@Override
public E next() {
E ret = data[cur];
cur = (cur+1)%data.length;
return ret;
}
}
}
测试类
package 动态数组;
public class TestArrayDeque {
public static void main(String[] args) {
ArrayDeque<Integer> deque =new ArrayDeque<>();
System.out.println(deque);
deque.addFirst(1);
deque.addFirst(2);
deque.addFirst(3);
System.out.println(deque);
deque.addLast(1);
deque.addLast(2);
deque.addLast(3);
System.out.println(deque);
}
}