双端队列的实现原理及概念
每日笑话:你好;uc浏览器更新以后,不仅是笑话没有了, 其它好用点的功能都没有了, 没有小说书架,不能缓存正本小说等, uc浏览器更新以后,变得很垃圾, 跟换了个浏览器似的,现在很多网友因此不在使用uc浏览器了,谢谢望采纳。
双端队列的定义
定义: 双端队列是限定插入和删除操作在表的两端进行的线性表。这两端分别称做端点1和端点2。也可像栈一样,可以用一个铁道转轨网络来比喻双端队列。在实际使用中,还可以有输出受限的双端队列(即一个端点允许插入和删除,另一个端点只允许插入的双端队列)和输入受限的双端队列(即一个端点允许插入和删除,另一个端点只允许删除的双端队列)。而如果限定双端队列从某个端点插入的元素只能从该端点删除,则该双端队列就蜕变为两个栈底相邻的栈了。双端队列(double ended queue,deque)是限定插入和删除操作在表两端进行的线性表,是具有队列和栈性质的数据结构。双端对列与普通队列的区别在于,双端队列可以在队列的头添加元素,队尾删除元素。
双端队列的实现
双端队列和循环队列的创建过程类似,都需要两个类似指针的标签,分别指向对首和队尾的下一个,因为要留一个null空间出来,方便判断队列满的条件。如下图:
初始状态front、rear都是指向双端队列的头部,图中的显示并不是表示循环对列从中间开始增加元素,并往两头走的情况。所以这一点还是值得注意!
示意图
1.初始状态
2.增添元素
(1)addLast();队尾添加元素
(2.addFirst());队头添加元素
3.删除元素
(1)removeLast();
(2)removeFirst();移除列首元素
实现代码
Deque接口
package 数据结构线性结构;
public interface Deque<E> extends Iterable<E> {//双端对列的接口
public void addFirst(E element);//在列首添加元素
public void addLast(E element);//在列尾添加元素
public E removeFirst();//在列首删除元素
public E removeLast();//在列尾部删除元素
public E getFirst();//获取列首元素
public E getLast();//获取列尾元素
public int size();//获取有效长度
public boolean isEmpty();//判段是否为空
}
ArrayDeque类------双端队列实现类
package 数据结构线性结构;
import java.util.Iterator;
public class ArrayDeque<E> implements Deque<E> {
private E[] data;
private int size;
private int front;
private int rear;
private static int DEFAULIT_CAPACITY = 10;
public ArrayDeque() {
size = 0;
rear = 0;
front = 0;
data = (E[])new Object[DEFAULIT_CAPACITY+1];
}
@Override
public Iterator<E> iterator() {
// TODO 自动生成的方法存根
return null;
}
private class ArrayDequeiterator<E> implements Iterator<E>{
private int cur =front;
@Override
public boolean hasNext() {
// TODO 自动生成的方法存根
return cur!=rear;
}
@Override
public E next() {
// TODO 自动生成的方法存根
E ret = (E) data[cur];
cur = (cur+1)%data.length;
return ret;
}
}
@Override
public void addFirst(E element) {//往列头添加元素
// TODO 自动生成的方法存根
if((rear+1)%data.length==front) {//判断队列满的时候
resize(2*data.length-1);//扩容的方法
}
front = (front-1+data.length)%data.length;//防止列表头指针溢出,所以进行取data.length余数
data[front] = element;
size++;
}
public void resize(int newlength) {//扩容
E[] newData =(E[]) new Object[newlength];//定义一个新元素数组
int i = 0;//计数
while(front!=rear) {//当遍历到front==rear,循环列表遍历结束
newData[i++] = this.data[front];
front = (front+1)%data.length;
}
data = newData;
front = 0;
rear = i;
}
@Override
public void addLast(E element) {
// TODO 自动生成的方法存根
if((rear+1)%data.length==front) {
resize(2*data.length-1);
}
data[rear]=element;
rear = (rear+1)%data.length;
size++;
}
@Override
public E removeFirst() {
// TODO 自动生成的方法存根
E ret = data[front];//取元素
if(size<(data.length-1)/4&&data.length-1>DEFAULIT_CAPACITY) {//缩容
resize(data.length/2+1);
}
front = (front+1)%data.length;
size--;
return ret;
}
@Override
public E removeLast() {
if(size<(data.length-1)/4&&data.length-1>DEFAULIT_CAPACITY) {
resize(data.length/2+1);
}
rear = (rear-1+data.length)%data.length;
E ret = data[rear];
size--;
return ret;
}
@Override
public E getFirst() {
// TODO 自动生成的方法存根
return data[front];
}
@Override
public E getLast() {
// TODO 自动生成的方法存根
return data[rear-1];
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('{');
int i =rear,j=front;
while(rear!=front) {
sb.append(data[front]);
front = (front+1)%data.length;
if(rear==front) {
sb.append('}');
break;
}else {
sb.append(',');
}
}
rear = i;
front = j;
return sb.toString();
}
@Override
public int size() {
// TODO 自动生成的方法存根
return size;
}
@Override
public boolean isEmpty() {
// TODO 自动生成的方法存根
return size==0;
}
}
ArrayDequeTest测试类:
package 数据结构线性结构;
public class DequeTest {
public static void main(String[] args) {
// TODO 自动生成的方法存根
ArrayDeque <Integer>que = new ArrayDeque<>();
que.addFirst(new Integer(1));
que.addFirst(new Integer(2));
que.addFirst(new Integer(3));
que.addFirst(new Integer(4));
que.addLast(new Integer(5));
que.addLast(new Integer(6));
que.addLast(new Integer(7));
que.addLast(new Integer(8));
System.out.println(que);
System.out.println(que.removeLast());
System.out.println(que.removeFirst());
System.out.println(que);
}
}
结果