学习目标
学习栈的原理及基本实现学习队列的原理及基本实现熟练使用 java 中的栈和队列
目录
1.栈(stack)
1.1概念
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出 LIFO ( Last In First Out )的原则。压栈:栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶 。出栈:栈的删除操作叫做出栈。 出数据在栈顶
后进先出(Last In Fist Out)
中缀表达式 转 后缀表达式
(5+4)*3-2
先乘除后加减
1 按运算顺序加括号
((5+4)*3)+号移出来一个括号 *也移出来一个括号 -再移出来
(((54)+3)* 2)-再将所有括号去掉
54+3*2- 得到后缀表达式
如何通过一个后缀表达式来计算一个值呢
这时候就需要借助栈

帮助手册 或按住CTRL alt f7
import java.util.Stack;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 星有野
* Date: 2022-05-09
* Time: 18:25
*/
public class Demo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push( 1);
stack.push( 2);
stack.push( 3);
stack.push( 4);
System.out.println(stack.pop());
}
}
4
3
3
false
false
为什么可以调用 isempty呢
因为
class Stack<E> extends Vector<E>子类
1.2实现
public class MyStack{
// 简单起见,我们就不考虑扩容问题了
private int[] array = new int[100];
private int size = 0;
public void push(int v) {
array[size++] = v;
}
public int pop() {
return array[--size];
}
public int peek() {
return array[size - 1];
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
}
2.队列
2.1概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾( Tail/Rear ) 出队列:进行删除操作的一端称为 队头 ( Head/Front )
2.2实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会
class Node {
int val;
Node next;
Node(int val, Node next) {
this.val = val; this.next = next;
}
Node(int val) { this(val, null);
}
}
public class MyQueue {
private Node head = null;
private Node tail = null;
private int size = 0;
public void offer(int v) {
Node node = new Node(v);
if (tail == null) { head = node;
}
else { tail.next = node;
}
tail = node; size++;
}
public int poll(){
if (size == 0) {
throw new RuntimeException("队列为空");
}
Node oldHead = head;
head = head.next;
if (head == null) {
tail = null;
}
size--;
return oldHead.val;
}
public int peek() {
if (size == 0) {
throw new RuntimeException("队列为空");
}
return head.val;
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
}
2.3循环队列
实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。
3.双端队列
3.1 概念
双端队列( deque )是指允许两端都可以进行入队和出队操作的队列, deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
4.Java 中的栈和队列
Stack
方法 | 解释 |
E push(E item) | 压栈 |
E poo() | 出栈 |
E peek() | 查看栈顶元素 |
boolean empty() | 判断栈是否为空 |
错误处理 | 抛出异常 | 返回特殊值 |
入队列 | add(e) | offer(e) |
出队列 | remove() | poll() |
队首元素 | element() | peek() |
5.面试题
1.
括号匹配问题。
OJ
链接
2.
用队列实现栈。
OJ
链接
3.
用栈实现队列。
OJ
链接
4.
实现一个最小栈。
OJ
链接
5.
设计循环队列。
OJ
链接
public class TestDemo {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0; i < s.length();i++) {
char ch = s.charAt(i);
if(ch == '(' || ch == '[' || ch == '{') {
//如果是左括号 直接入栈
stack.push(ch);
}else{
//遇到了右括号
if(stack.empty()) {
//右括号多
System.out.println("右括号多");
return false;
}
char top = stack.peek();//哪个左括号
if(top == '{' && ch == '}' || top == '[' && ch == ']' || top == '(' && ch == ')') {
stack.pop();
}else{
//左右括号不匹配
System.out.println("左右括号不匹配");
return false;
}
}
}
if(!stack.empty()) {
//左括号多
System.out.println("左括号多");
return false;
}
return true;
}
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
stack.push(6);
System.out.println(stack.pop());//弹出栈顶元素,并且删除 6
System.out.println(stack.pop());//弹出栈顶元素,并且删除 5
System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
System.out.println(stack.pop());//弹出栈顶元素,并且删除 3
System.out.println(stack.pop());//弹出栈顶元素,并且删除 2
System.out.println(stack.pop());//弹出栈顶元素,并且删除 1
System.out.println(stack.peek());//获取栈顶元素,但是不删除 5
System.out.println(stack.peek());//获取栈顶元素,但是不删除 5
System.out.println(stack.isEmpty());//false
}
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for(int i = 0;i < tokens.length;i++) {
String val = tokens[i];
if(isOperation(val) == false) {
//如果不是运算符
stack.push(Integer.parseInt(val));
}else {
//到底啥运算符????
int num2 = stack.pop();
int num1 = stack.pop();
switch(val) {
case "+":
stack.push(num1+num2);
break;
case "-":
stack.push(num1-num2);
break;
case "*":
stack.push(num1*num2);
break;
case "/":
stack.push(num1/num2);
break;
}
}
}
return stack.pop();
}
private boolean isOperation(String x) {
if(x.equals("+") || x.equals("-") ||x.equals("*") ||x.equals("/")) {
return true;
}
return false;
}
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> stack = new Stack<>();
int j = 0;//遍历popA
for(int i = 0; i < pushA.length;i++) {
stack.push(pushA[i]);
while(j < popA.length && !stack.empty() && stack.peek() == popA[j]) {
stack.pop();
j++;
}
}
return stack.empty();
}
public static void main1(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
System.out.println(stack.peek());//获取栈顶元素,但是不删除 3
System.out.println(stack.peek());//获取栈顶元素,但是不删除 3
System.out.println(stack.empty());
System.out.println("============");
System.out.println(stack.isEmpty());
}
}
内容重点总结
掌握栈和队列的数据结构知识并做简单实现
掌握
java
中栈、队列、双端队列的使用