目录
栈的定义
计算机科学中,栈是一种线性数据结构,只能在它的一端添加或移除元素
- 可以操作元素的一端叫做栈顶,另一端不能操作元素叫做栈底
- 添加元素的操作叫做入栈(或压栈),移除元素的操作叫出栈(或弹栈)
- 先进后出
自实现栈
可以通过多种方式来实现栈,如:链表、数组等。下面先定义栈的功能接口,然后分别用链表和数组来实现栈
定义栈接口
java
package algorithm.stack;
/**
* 栈接口:定义栈功能
*/
public interface Stack {
// 栈的最大容量:1024
int MAX_CAPACITY = 1 << 10;
/**
* 入栈/压栈
*/
boolean push(Object e);
/**
* 出栈/弹栈
*/
Object pop();
/**
* 查看栈顶元素
*/
Object peek();
/**
* 栈是否空
*/
boolean isEmpty();
/**
* 栈是否满
*/
boolean isFull();
}
基于链表实现栈
只能从栈顶操作元素是栈的特点之一,即只从一端添加元素或者移除元素就行,所以这里我选择用单项链表来实现栈
java
package algorithm.stack;
import java.util.Iterator;
/**
* 基于链表实现栈
*/
public class LinkedListStack implements Stack, Iterable<Object> {
// 虚拟头节点
private final Node dummyHead = new Node();
// 元素个数
private int size;
@Override
public boolean push(Object e) {
if (e == null) {
throw new NullPointerException();
}
if (isFull()) {
return false;
}
dummyHead.next = new Node(e, dummyHead.next);
size++;
return true;
}
@Override
public Object pop() {
Object e = peek();
if (e != null) {
dummyHead.next = dummyHead.next.next;
size--;
}
return e;
}
@Override
public Object peek() {
if (isEmpty()) {
return null;
}
return dummyHead.next.val;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean isFull() {
return size == MAX_CAPACITY;
}
@Override
public Iterator<Object> iterator() {
return new Iterator<Object>() {
Node p = dummyHead;
@Override
public boolean hasNext() {
return p.next != null;
}
@Override
public Object next() {
Node node = p.next;
p = p.next;
return node.val;
}
};
}
/**
* 定义数据节点
*/
private static class Node {
Object val;
Node next;
public Node() {
}
public Node(Object val, Node next) {
this.val = val;
this.next = next;
}
}
}
基于数组实现栈
这里再使用数组来实现栈,从数组的尾部来操作元素,性能要高一些,因为从数组0索引处添加或移除元素,会涉及到后续元素的移动,影响性能
java
package algorithm.stack;
import java.util.Arrays;
import java.util.Iterator;
/**
* 基于数组实现栈
*/
public class ArrayStack implements Stack, Iterable<Object> {
// 元素个数
private int size;
// 存储元素的数组
private Object[] container;
// 默认初始化容量
private static final int DEFAULT_INIT_CAPACITY = 16;
// 定义一个指针,方便栈顶操作元素
private int p = 0;
@Override
public boolean push(Object e) {
if (e == null) {
throw new NullPointerException();
}
if (isFull()) {
return false;
}
grow(size + 1);
addToContainer(e);
return true;
}
/**
* 扩容
*/
private void grow(int minCapacity) {
if (isEmpty()) {
container = new Object[DEFAULT_INIT_CAPACITY];
return;
}
int oldCapacity = container.length;
// 扩容为原来的两倍容量
int newCapacity = oldCapacity << 1;
newCapacity = Math.min(MAX_CAPACITY, newCapacity);
container = Arrays.copyOf(container, newCapacity);
}
/**
* 执行添加元素
*/
private void addToContainer(Object e) {
container[p] = e;
size++;
p++;
}
@Override
public Object pop() {
Object e = peek();
if (e != null) {
container[p--] = null;
size--;
}
return e;
}
@Override
public Object peek() {
if (isEmpty()) {
return null;
}
return container[p - 1];
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean isFull() {
return size == MAX_CAPACITY;
}
@Override
public Iterator<Object> iterator() {
return new Iterator<Object>() {
private int index = size - 1;
@Override
public boolean hasNext() {
return index >= 0;
}
@Override
public Object next() {
return container[index--];
}
};
}
}
LeetCode-102题
题解
java
class Solution {
public boolean isValid(String s) {
// check param
if (s == null || s.length() < 2) {
return false;
}
// 借助栈来解题(Java中的LinkedList可以用作栈)
LinkedList<Character> stack = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
char item = s.charAt(i);
if ('(' == item) {
stack.push(')');
} else if ('{' == item) {
stack.push('}');
} else if ('[' == item) {
stack.push(']');
} else {
if (!stack.isEmpty() && item == stack.peek()) {
stack.pop();
} else {
return false;
}
}
}
return stack.isEmpty();
}
}
测试结果

LeetCode-232题
题解
java
/**
* 注:题目上说明了所有的操作都是有效的,不会抛异常
*/
class MyQueue {
// 用于添加元素的栈
private LinkedList<Integer> stackEnter = new LinkedList<>();
// 用于移除元素的栈
private LinkedList<Integer> stackExit = new LinkedList<>();
public void push(int x) {
stackEnter.push(x);
}
public int pop() {
transferStack();
return stackExit.pop();
}
private void transferStack() {
if (!stackExit.isEmpty()) {
return;
}
while (!stackEnter.isEmpty()) {
stackExit.push(stackEnter.pop());
}
}
public int peek() {
transferStack();
return stackExit.peek();
}
public boolean empty() {
return stackEnter.isEmpty() && stackExit.isEmpty();
}
}
测试结果

LeetCode-225题
题解
java
/**
* 注:题目中说明所有操作都是有效操作
*/
class MyStack {
// Java中,LinkedList可以用作队列
// 定义两个队列
private final LinkedList<Integer> queueEnter = new LinkedList<>();
private final LinkedList<Integer> queueExit = new LinkedList<>();
public MyStack() {
}
public void push(int x) {
queueEnter.offer(x);
}
public int pop() {
transferQueue();
return queueExit.poll();
}
private void transferQueue() {
while (!queueEnter.isEmpty()) {
queueExit.offer(queueEnter.poll());
}
int size = queueExit.size();
for (int i = 0; i < size - 1; i++) {
queueExit.offer(queueExit.poll());
}
}
public int top() {
int pop = pop();
queueExit.offer(pop);
return pop;
}
public boolean empty() {
return queueEnter.isEmpty() && queueExit.isEmpty();
}
}
测试结果
