Deque--双向队列,支持同时在两端添加或删除元素--基于双向链表或动态数组的实现
支持以下API
isEmpty() 判断队列是否为空
size() 节点数量
pushLeft() 左端插入节点
pushRight() 右端插入节点
popLeft() 左端删除节点
popRight() 右端删除节点
代码
import java.util.Iterator;
/**
* @author 鯉伴MAY
* @param <Item>
*/
public class Deque <Item> implements Iterable<Item>{
public Deque() {}
private class DequeNode {
Item item;
DequeNode pre;
DequeNode next;
}
private DequeNode first;
private DequeNode last;
private int N;
public boolean isEmpty(){
return first == null;
}
public int size() {
return N;
}
//创建新的节点
private DequeNode newNode(Item item) {
DequeNode temp = new DequeNode();
temp.item = item;
return temp;
}
//从左端插入节点
public void pushLeft(Item item) {
DequeNode xNode = newNode(item);
if(isEmpty()) {
first = xNode;
last = xNode;
}else {
xNode.next = first;
first.pre = xNode;
first = xNode;
}
N++;
}
//从右端插入节点
public void pushRight(Item item) {
DequeNode xNode = newNode(item);
if(isEmpty()) {
first = xNode;
last = xNode;
}else {
last.next = xNode;
xNode.pre = last;
last = xNode;
}
N++;
}
//从左端弹出节点
public Item popLeft() {
if(isEmpty()){
System.out.println("栈已空");
return null;
}
DequeNode temp = first;
if(size() == 1) {
first = null;
last = null;
}else {
first = first.next;
first.pre = null;
temp.next = null;
}
N--;
return temp.item;
}
//从右端弹出节点
public Item popRight() {
if(isEmpty()) {
System.out.println("队列已空");
return null;
}
DequeNode temp = last;
if(size() == 1) {
first = null;
last = null;
}else {
last = last.pre;
last.next = null;
temp.pre = null;
}
N--;
return temp.item;
}
public void printStack() {
DequeNode temp = first;
while(temp != null) {
System.out.println(temp.item);
temp = temp.next;
}
}
@Override
public Iterator<Item> iterator() {
return new LIterator();
}
private class LIterator implements Iterator<Item>{
private DequeNode current = first;
@Override
public boolean hasNext() {
return current != null;
}
@Override
public Item next() {
Item item = current.item;
current = current.next;
return item;
}
}
}
基于动态数组分配的实现
在实现过程中,我们检测队列的大小是否小于数组的四分之一,如果小于,则将长度减半,此时数组状态约为半满,在下次改变数组大小之前仍可以多次push和pop,同时,检测队列是否装满数组,如果装满,则将数组长度加倍。这样,栈不会溢出,且使用率也永远高于四分之一。
public class ResizingArrayDeque<Item> {
private int cap = 5;//数组的容量初始值设为5
private Item[] array;
private int N;
public ResizingArrayDeque() {
array = (Item[]) new Object[cap];
}
private void resize(int max){
Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < N; i++) {
temp[i] = array[i];
}
array = temp;
}
public boolean isEmpty() {
return N==0;
}
public int size(){
return N;
}
public void pushLeft(Item item) {
if(N == array.length)
resize(2*array.length);
//往后循环移位,空出第一位
for (int i = N; i >0 ; i--) {
array[i]=array[i-1];
}
array[0] = item;
N++;
}
public void pushRight(Item item) {
if(N == array.length)
resize(2*array.length);
array[N++] = item;
}
public Item popLeft() {
if(N==0){
System.out.println("队列已空");
return null;
}
//弹出第一位,往前递补
Item temp = array[0];
for(int i=0;i<N-1;i++) {
array[i] = array[i+1];
}
array[N-1] = null;
N--;
if(N>0 && N == array.length/4)
resize(array.length/2);
return temp;
}
public Item popRight() {
if(N==0){
System.out.println("队列已空");
return null;
}
Item temp = array[--N];
array[N] = null;//置空,避免对象游离
if(N>0 && N == array.length/4)
resize(array.length/2);
return temp;
}
}