> 文章列表 > 笔试常考: 队列实现栈 and 栈实现队列 and 验证栈序列

笔试常考: 队列实现栈 and 栈实现队列 and 验证栈序列

笔试常考: 队列实现栈 and 栈实现队列 and 验证栈序列

目录

一.浅谈栈和队列

1.栈

2.队列

二.Java中的栈和队列

1.Java中的栈

2.Java中的队列

3.双端队列

1.LinkedList

 2.ArrayDeque

三.队列来实现栈

1.双队列实现栈

1.问题分析

2.代码实现

2.单队列实现栈

1.问题分析

2.代码实现

四.栈实现队列

1.双栈实现队列

1.问题分析

2.代码实现

五.验证栈序列

1.题目描述

2.问题分析

3.代码实现


一.浅谈栈和队列

1.栈

我们都熟知栈是一种先进后出数据结构,数据只能从一段进入,从这一段出去

如下图就是抽象的栈结构,数据只能从右端进入,从右端出去,例如只能弹出5(也就是最后插入的元素),要进入6元素,只能在5的后面

2.队列

我们都熟知队列是一种先进后出的数据结构,数据从一段进出,并从另一端出去

如下图就是抽象的队列结构,数据只能从左端出,从右端进入,例如只能先弹出1(也就是最先进入队列的元素),也只能在右端插入新数据6

二.Java中的栈和队列

1.Java中的栈

Java API中有专门的栈的API,如图,但是这个类用来实现栈的效率十分低,因为Vector是一个线程安全的类,因此在具体的使用中,我们不建议创建Stack的对象.推荐的我们放在了第三个:双端队列

2.Java中的队列

Java中没有命名为Queue的类,但是相应的接口,我们不可以直接创建Queue的对象,因为Queue是接口不是类,但是有实现Queue接口的队列,具体看第三个:双端队列

3.双端队列

双端队列虽然叫队列,但他同样也可以实现栈的功能,因此一种API既可以实现栈,也可以实现队列,都有具体的实现方法

我们都知道队列和栈有两种实现的方式,线性表(数组)和链表,同样的双端队列也有两种实现的方式

1.LinkedList

LinkedList底层使用链表来实现的,现在我们来具体介绍一下实现队列和栈的功能的API

LinkedList<Integer> stack = new LinkedList<>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
System.out.println(stack);//[4, 3, 2, 1]
System.out.println(stack.pop());//4
System.out.println(stack.peek());//3

从以上方法可以看出,LinkedList的确可以实现栈的功能,只需要使用push和pop方法即可

队列

LinkedList<Integer> queue = new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
System.out.println(queue);//[1, 2, 3, 4]
System.out.println(queue.poll());//1
System.out.println(queue.peek());//2

 从以上方法可以看出,LinkedList的确可以实现队列的功能,只需要使用offer和poll方法即可

总结: 按我的理解就是当执行offer方法的时候,就是在链表的尾部插入数据,执行push方法的时候,就是在链表的头部插入数据,当执行poll方法的时候,就是在链表的头部删除数据,执行pop方法的时候,就是在链表的尾部删除数据,peek方法就是取出链表头部的数据,我们可以使用peekLast取出链表尾部的数据

 2.ArrayDeque

LinkedList底层使用数组来实现的,现在我们来具体介绍一下实现队列和栈的功能的API

具体方法调用和LinkedList一模一样,只是new对象不同,这里不做更多的介绍

ArrayDeque<Integer> queue = new ArrayDeque<>();

三.队列来实现栈

力扣上专门的题目,在这里可以作参考:力扣

1.双队列实现栈

1.问题分析

我们都知道栈最后入栈的元素最先出栈,而队列最先入栈的元素最后出栈.

用队列来实现栈,我们需要考虑的就是如何将最先入队列的元素置入队列的尾端,最后入队列的元素置入队列的首端(正好符合栈的出栈序列),也就是说原本的{1,2,3,4}顺序,现在需要以{4,3,2,1}顺序存储到队列中.我们可以用双队列来执行

  • 将元素1入队列
  • 将元素2入队列

  • 将元素3入队列

  • 将元素4入队列

 

 以上便可以用双队列达到了栈的效果,但是我们这样每次数据保存的在队列的位置不确定,我们不妨每次将queue1和queue2的引用进行交换,使得每次queue1引用指向的队列就是我们存放数据的队列.

2.代码实现

class MyStack {//存储元素的队列private LinkedList<Integer> queue1 = new LinkedList<>();//辅助队列private LinkedList<Integer> queue2 = new LinkedList<>();public MyStack() {}public void push(int x) {queue2.offer(x);while(!empty()){queue2.offer(queue1.pop());   }LinkedList<Integer> temp=queue1;queue1=queue2;queue2=temp;}public int pop() {if (empty()) {return -1;}return queue1.poll();}public int top() {if (empty()) {return -1;}return queue1.peek();}public boolean empty() {return queue1.isEmpty();}}

2.单队列实现栈

1.问题分析

经历了上面的双队列实现栈,我们其实可以很容易的想到如何使用单队列实现栈的功能,我们只需要每次入队列指定的元素,然后将队列之前的元素重新入队列,便可以实现栈的功能,接下来看演示

  • 将元素1入队列
  • 将元素2入队列
  • 将元素3入队列
  • 将元素4入队列

 

2.代码实现

class MyStack {private LinkedList<Integer> queue = new LinkedList<>();public MyStack() {}public void push(int x) {queue.offer(x);int size=queue.size();for(int i=0;i<size-1;++i){queue.offer(queue.poll());}}public int pop() {return queue.poll();}public int top() {return queue.peek();}public boolean empty() {return queue.size()==0;}
}

四.栈实现队列

 力扣上专门的题目,在这里可以作参考:力扣

1.双栈实现队列

1.问题分析

可能很多人会想单队列能够实现栈,单栈一定也能够实现队列,其实我们只能用双栈来实现队列,这是因为栈的特殊性,所以我们这里来讨论双栈实现队列的思路

因为队列的先进先出的,所以这里栈一定要把先进的元素放在栈的顶部,这样才能够满足队列的结构,也就是说我们要把栈的结构倒转过来,这时候一定需要另一个栈的辅助,比如入栈的顺序为{1,2,3,4},这个时候放入到栈中的顺序应该为{4,3,2,1},这样出栈的顺序满足出队列的先进先出的原则.接下里我们使用演示的方式看看如何实现这个功能

  • 将元素1入队列
  • 将元素2入队列
  • 将元素3入队列
  • 将元素4入队列

 

2.代码实现

class MyQueue {LinkedList<Integer> stack1=new LinkedList<>();LinkedList<Integer> stack2=new LinkedList<>();public MyQueue() {}public void push(int x) {while(!stack1.isEmpty()){stack2.push(stack1.pop());}stack1.push(x);while(!stack2.isEmpty()){stack1.push(stack2.pop());}}public int pop() {int val=stack1.pop();return val;}public int peek() {        return stack1.peek();}public boolean empty() {return stack1.isEmpty();}
}

五.验证栈序列

1.题目描述

给定 pushed 和 popped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。

力扣:力扣

2.问题分析

对于一个序列,因为我们可以在入栈的同时进栈,所以出栈的可以有多种顺序,例如对A,B,C,D入栈,出栈的顺序不一定是D,C,B,A,因为随时可以出栈,比如入栈一个出栈一个,出栈的顺序就为:A,B,C,D

因此判断是否为栈序列,我们判断栈顶元素是否为popped的元素,如果不是将pushed的元素进行入栈,直到栈顶元素为popped的元素,然后对入栈的pushed元素依次进行出栈,直到栈顶的元素不为popped的出栈序列

3.代码实现

    public boolean validateStackSequences(int[] pushed, int[] popped) {LinkedList<Integer> stack = new LinkedList<>();int i=0;for(int val:pushed){stack.push(val);while(!stack.isEmpty()&&stack.peek()==popped[i]){stack.pop();i++;}}return stack.isEmpty();}

大学排行榜