public class LinkedListStack<E> implements Stack<E>, Iterable<E> {
private final int capacity;
private int size;
private final Node<E> head = new Node<>(null, null);
public LinkedListStack(int capacity) {
this.capacity = capacity;
}
@Override
public boolean push(E value) {
if (isFull()) {
return false;
}
head.next = new Node<>(value, head.next);
size++;
return true;
}
@Override
public E pop() {
if (isEmpty()) {
return null;
}
Node<E> first = head.next;
head.next = first.next;
size--;
return first.value;
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
return head.next.value;
}
@Override
public boolean isEmpty() {
return head.next == null;
}
@Override
public boolean isFull() {
return size == capacity;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Node<E> p = head.next;
@Override
public boolean hasNext() {
return p != null;
}
@Override
public E next() {
E value = p.value;
p = p.next;
return value;
}
};
}
static class Node<E> {
E value;
Node<E> next;
public Node(E value, Node<E> next) {
this.value = value;
this.next = next;
}
}
}
3.数组实现
java复制代码
public class ArrayStack<E> implements Stack<E>, Iterable<E>{
private final E[] array;
private int top = 0;
@SuppressWarnings("all")
public ArrayStack(int capacity) {
this.array = (E[]) new Object[capacity];
}
@Override
public boolean push(E value) {
if (isFull()) {
return false;
}
array[top++] = value;
return true;
}
@Override
public E pop() {
if (isEmpty()) {
return null;
}
return array[--top];
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
return array[top-1];
}
@Override
public boolean isEmpty() {
return top == 0;
}
@Override
public boolean isFull() {
return top == array.length;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int p = top;
@Override
public boolean hasNext() {
return p > 0;
}
@Override
public E next() {
return array[--p];
}
};
}
}
4.应用
模拟如下方法调用
java复制代码
public static void main(String[] args) {
System.out.println("main1");
System.out.println("main2");
method1();
method2();
System.out.println("main3");
}
public static void method1() {
System.out.println("method1");
method3();
}
public static void method2() {
System.out.println("method2");
}
public static void method3() {
System.out.println("method3");
}
模拟代码
java复制代码
public class CPU {
static class Frame {
int exit;
public Frame(int exit) {
this.exit = exit;
}
}
static int pc = 1; // 模拟程序计数器 Program counter
static ArrayStack<Frame> stack = new ArrayStack<>(100); // 模拟方法调用栈
public static void main(String[] args) {
stack.push(new Frame(-1));
while (!stack.isEmpty()) {
switch (pc) {
case 1 -> {
System.out.println("main1");
pc++;
}
case 2 -> {
System.out.println("main2");
pc++;
}
case 3 -> {
stack.push(new Frame(pc + 1));
pc = 100;
}
case 4 -> {
stack.push(new Frame(pc + 1));
pc = 200;
}
case 5 -> {
System.out.println("main3");
pc = stack.pop().exit;
}
case 100 -> {
System.out.println("method1");
stack.push(new Frame(pc + 1));
pc = 300;
}
case 101 -> {
pc = stack.pop().exit;
}
case 200 -> {
System.out.println("method2");
pc = stack.pop().exit;
}
case 300 -> {
System.out.println("method3");
pc = stack.pop().exit;
}
}
}
}
}
二.栈题目
1.有效的括号-力扣 20 题
一个字符串中可能出现 []() 和 {} 三种括号,判断该括号是否有效
有效的例子
()[]{}
([{}])
()
无效的例子
[)
([)]
([]
思路
遇到左括号, 把要配对的右括号放入栈顶
遇到右括号, 若此时栈为空, 返回 false,否则把它与栈顶元素对比
若相等, 栈顶元素弹出, 继续对比下一组
若不等, 无效括号直接返回 false
循环结束
若栈为空, 表示所有括号都配上对, 返回 true
若栈不为空, 表示右没配对的括号, 应返回 false
答案(用到了课堂案例中的 ArrayStack 类)
java复制代码
public boolean isValid(String s) {
ArrayStack<Character> stack = new ArrayStack<>(s.length() / 2 + 1);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
stack.push(')');
} else if (c == '[') {
stack.push(']');
} else if (c == '{') {
stack.push('}');
} else {
if (!stack.isEmpty() && stack.peek() == c) {
stack.pop();
} else {
return false;
}
}
}
return stack.isEmpty();
}
public class E03InfixToSuffix {
/*
思路
1. 遇到数字, 拼串
2. 遇到 + - * /
- 优先级高于栈顶运算符 入栈
- 否则将栈中高级或平级运算符出栈拼串, 本运算符入栈
3. 遍历完成, 栈中剩余运算符出栈拼串
- 先出栈,意味着优先运算
4. 带 ()
- 左括号直接入栈
- 右括号要将栈中直至左括号为止的运算符出栈拼串
| |
| |
| |
_____
a+b
a+b-c
a+b*c
a*b+c
(a+b)*c
*/
public static void main(String[] args) {
System.out.println(infixToSuffix("a+b"));
System.out.println(infixToSuffix("a+b-c"));
System.out.println(infixToSuffix("a+b*c"));
System.out.println(infixToSuffix("a*b-c"));
System.out.println(infixToSuffix("(a+b)*c"));
System.out.println(infixToSuffix("a+b*c+(d*e+f)*g"));
}
static String infixToSuffix(String exp) {
LinkedList<Character> stack = new LinkedList<>();
StringBuilder sb = new StringBuilder(exp.length());
for (int i = 0; i < exp.length(); i++) {
char c = exp.charAt(i);
switch (c) {
case '+', '-', '*', '/' -> {
if (stack.isEmpty()) {
stack.push(c);
} else {
if (priority(c) > priority(stack.peek())) {
stack.push(c);
} else {
while (!stack.isEmpty()
&& priority(stack.peek()) >= priority(c)) {
sb.append(stack.pop());
}
stack.push(c);
}
}
}
case '(' -> {
stack.push(c);
}
case ')' -> {
while (!stack.isEmpty() && stack.peek() != '(') {
sb.append(stack.pop());
}
stack.pop();
}
default -> {
sb.append(c);
}
}
}
while (!stack.isEmpty()) {
sb.append(stack.pop());
}
return sb.toString();
}
static int priority(char c) {
return switch (c) {
case '(' -> 0;
case '*', '/' -> 2;
case '+', '-' -> 1;
default -> throw new IllegalArgumentException("不合法字符:" + c);
};
}
}
4.双栈模拟队列-力扣 232 题
给力扣题目用的自实现栈,可以定义为静态内部类
java复制代码
class ArrayStack<E> {
private E[] array;
private int top; // 栈顶指针
@SuppressWarnings("all")
public ArrayStack(int capacity) {
this.array = (E[]) new Object[capacity];
}
public boolean push(E value) {
if (isFull()) {
return false;
}
array[top++] = value;
return true;
}
public E pop() {
if (isEmpty()) {
return null;
}
return array[--top];
}
public E peek() {
if (isEmpty()) {
return null;
}
return array[top - 1];
}
public boolean isEmpty() {
return top == 0;
}
public boolean isFull() {
return top == array.length;
}
}
参考解答,注意:题目已说明
调用 push、pop 等方法的次数最多 100
java复制代码
public class E04Leetcode232 {
/*
队列头 队列尾
s1 s2
顶 底 底 顶
abc
push(a)
push(b)
push(c)
pop()
*/
ArrayStack<Integer> s1 = new ArrayStack<>(100);
ArrayStack<Integer> s2 = new ArrayStack<>(100);
public void push(int x) {
s2.push(x);
}
public int pop() {
if (s1.isEmpty()) {
while (!s2.isEmpty()) {
s1.push(s2.pop());
}
}
return s1.pop();
}
public int peek() {
if (s1.isEmpty()) {
while (!s2.isEmpty()) {
s1.push(s2.pop());
}
}
return s1.peek();
}
public boolean empty() {
return s1.isEmpty() && s2.isEmpty();
}
}
5.单队列模拟栈-力扣 225 题
给力扣题目用的自实现队列,可以定义为静态内部类
java复制代码
public class ArrayQueue3<E> {
private final E[] array;
int head = 0;
int tail = 0;
@SuppressWarnings("all")
public ArrayQueue3(int c) {
c -= 1;
c |= c >> 1;
c |= c >> 2;
c |= c >> 4;
c |= c >> 8;
c |= c >> 16;
c += 1;
array = (E[]) new Object[c];
}
public boolean offer(E value) {
if (isFull()) {
return false;
}
array[tail & (array.length - 1)] = value;
tail++;
return true;
}
public E poll() {
if (isEmpty()) {
return null;
}
E value = array[head & (array.length - 1)];
head++;
return value;
}
public E peek() {
if (isEmpty()) {
return null;
}
return array[head & (array.length - 1)];
}
public boolean isEmpty() {
return head == tail;
}
public boolean isFull() {
return tail - head == array.length;
}
}
参考解答,注意:题目已说明
调用 push、pop 等方法的次数最多 100
每次调用 pop 和 top 都能保证栈不为空
java复制代码
public class E05Leetcode225 {
/*
队列头 队列尾
cba
顶 底
queue.offer(a)
queue.offer(b)
queue.offer(c)
*/
ArrayQueue3<Integer> queue = new ArrayQueue3<>(100);
int size = 0;
public void push(int x) {
queue.offer(x);
for (int i = 0; i < size; i++) {
queue.offer(queue.poll());
}
size++;
}
public int pop() {
size--;
return queue.poll();
}
public int top() {
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
}