用队列实现栈
当要弹出元素3 时 必须先弹出元素1 并将1 添加到queueB中,再弹出元素2 将2 添加到queueB的元素1 后面queueB中的元素顺序为1,2 此时若想添加元素4 则直接在queueB中添加即可。
与用栈实现队列不同的是queueA和QueueB 交替使用(因为顺序未发生改变)
import p1.接口.Stack;
import java.util.Iterator;
public class QueueToStack {
//队列实现栈
public static void main(String[] args) {
StackImplByQueue <Integer>stack = new StackImplByQueue<>();
System.out.println(stack);
for(int i =1 ;i <=5 ;i++){
stack.push(i);//A中
}
System.out.println(stack);
System.out.println(stack.pop());
System.out.println(stack);//B中
}
}
class StackImplByQueue<E> implements Stack<E> {
private ArrayQueue<E> queueA;
private ArrayQueue<E> queueB;
public StackImplByQueue(){
queueA = new ArrayQueue<>();
queueB = new ArrayQueue<>();
}
@Override
public int size() {
if(queueA.isEmpty() && queueB.isEmpty()){
return 0;
}else if(!queueA.isEmpty()){
return queueA.size();
}else{
return queueB.size();
}
}
@Override
public boolean isEmpty() {
return queueA.isEmpty()&& queueB.isEmpty();
}
@Override
public void push(E element) {
if(queueA.isEmpty() && queueB.isEmpty()){
queueA.offer(element);
}else if(!queueA.isEmpty()){
queueA.offer(element);
}else{
queueB.offer(element);
}
}
@Override
public E pop() {
if(isEmpty()){
return null;
}
E ret = null;
if(!queueA.isEmpty()){
while (queueA.size()!=1){
queueB.offer(queueA.poll());
}
ret = queueA.poll();
}else{
while (queueB.size()!=1){
queueA.offer(queueB.poll());
}
ret = queueB.poll();
}
return ret;
}
@Override
public E peek() {
if(isEmpty()){
return null;
}
E ret = null;
if(!queueA.isEmpty()){
while (queueA.size()!=1){
queueB.offer(queueA.poll());
}
ret = queueA.poll();
queueB.offer(ret);
}else{
while (queueB.size()!=1){
queueA.offer(queueB.poll());
}
ret = queueB.poll();
queueA.offer(ret);
}
return ret;
}
@Override
public void clear() {
queueA.clear();
queueB.clear();
}
@Override
public String toString() {
if(isEmpty()){
return "[]";
}else if(!queueA.isEmpty()){
return queueA.toString();
}else {
return queueB.toString();
}
}
@Override
public Iterator<E> iterator() {
if(isEmpty()){
return queueA.iterator();
}else if (!queueA.isEmpty()){
return queueA.iterator();
}else {
return queueB.iterator();
}
}
}
循环队列
ArrayQueue
- 队列的顺序存储结构本身就是由ArrayList实现的
- 在数据元素入栈时,在表尾添加元素
- 在数据元素出栈时,在表头删除元素
- 入队的事件复杂度时O(1) ,出队的时间复杂度O(n)(不是平均是每次)
时间复杂度太高(我们期望它的时间复杂度和栈一样,入队和出队都为O(1))
- 优化1 :让队头指针和队尾指针一样随着数据元素的变化而移到
这样操作入队和出队的操作都是O(1)
但是rear指针最后就不能在继续向后移动了
并且造成了空间浪费
- 优化2: 当队尾或队头指针到达尾部时,如需后移可重新指向表头
解决了空间浪费问题
问题:判空和判满条件冲突
队列满的条件:(Rear +1)% n == Front
队列空的条件:(Rear +1)% n == Front
- 优化3 将一个空间预留出来不存任何元素,尾指针始终指向null这个空间
队列满的条件:(Rear +1)% n == Front
队列空的条件:Rear == front
循环队列底层是动态数组(不能直接由ArrayList 和ArrayQueue实现)