栈(英语:stack)又称为栈或堆叠,是计算机科学中一种特殊的串列形式的抽象数据类型,其特殊之处在于只能允许在链表或数组的一端(称为堆栈顶端指针,英语:top)进行加入数据(英语:push)和输出数据(英语:pop)的运算。另外栈也可以用一维数组或链表的形式来完成。堆栈的另外一个相对的操作方式称为队列。
由于堆栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。
其基本的结构,如下图:
操作模型简图
参考了一篇BLOG,借用其中的图片,可以很清晰的看到其模型(侵立删):
抽象方法模型
- 初始化 init: -> Stack
- 出栈 push: N x Stack -> Stack
- 获取栈顶元素,不出栈 peek: Stack -> (N U ERROR)
- 出栈 pop: Stack -> Stack
- 是空栈 isempty: Stack -> Boolean
JAVA接口定义
public interface StackInterface<T> {
/**
* 出栈
*
* @return
*/
T pop();
/**
* 进栈
*
* @param t
*/
void push(T t);
/**
* 获取栈顶元素,未出栈
*
* @return
*/
T peek();
/**
* 检查是否为空栈
*
* @return
*/
boolean isEmpty();
/** 清空栈 */
void clear();
/**
* 当前栈深度
*
* @return
*/
int length();
}
栈的实现代码
package com.tao.struct.stack;
public class BaseStack<T> implements StackInterface<T> {
// 默认栈的空间长度
private final int DEFAULT_STACK_SIZE = 8;
// 当前栈的指向
private int top = -1;
T[] objects = null;
public BaseStack() {
//JAVA 不支持泛型数组,只能这么做了 :):grimacing:
objects = (T[]) new Object[DEFAULT_STACK_SIZE];
}
@Override
public T pop() {
if (isEmpty()) {
return null;
}
T t = objects[top--];
return t;
}
@Override
public void push(T t) {
if (top >= DEFAULT_STACK_SIZE - 1) {
throw new IllegalStateException("栈已满,无法进栈,最大深度 " + DEFAULT_STACK_SIZE);
}
objects[++top] = t;
}
@Override
public T peek() {
if (isEmpty()) {
return null;
}
T object = objects[top];
return object;
}
@Override
public boolean isEmpty() {
return top == -1;
}
@Override
public void clear() {
objects = (T[]) new Object[DEFAULT_STACK_SIZE];
top = -1;
}
@Override
public int length() {
return top;
}
}
测试代码
为了实现创建的栈的测试,我们这里写了一个简单POJO对象,作为测试使用,也可以自己尝试创建一个对象
class Person {
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
创建一个栈对象,使用其方法测试
public class TestBaseStack {
public static void main(String[] args) {
BaseStack<Person> stack = new BaseStack<>();
System.out.println("--------------------------循环新增测试--------------------------");
for (int i = 0; i < 8; i++) {
Person person = new Person("姓名:" + i, i);
stack.push(person);
}
System.out.println("新增栈元素完成 当前栈深度 = " +stack.length());
System.out.println("--------------------------测试满栈--------------------------");
try {
stack.push(new Person("测试", 0));
} catch (IllegalStateException ex) {
System.out.println(ex.getMessage());
}
System.out.println("--------------------------循环测试出栈--------------------------");
while (stack.peek() != null) {
// 获取栈顶元素出栈
System.out.println("出栈元素为 ------>" + stack.pop());
}
// 新增栈元素
System.out.println("--------------------------新增栈元素测试--------------------------");
stack.push(new Person("测试账户",12));
// 显示入栈元素
System.out.println("栈顶元素为 ------>" + stack.peek());
System.out.println("--------------------------清空栈测试--------------------------");
System.out.println("当前栈是否为空 ------> " + stack.isEmpty());
stack.clear();
System.out.println("当前栈是否为空 ------> " + stack.isEmpty());
}
}
测试效果
可以看到实现了基本的栈的功能,后期我们将尝试使用Stack的应用场景.
--------------------------循环新增测试--------------------------
新增栈元素完成 当前栈深度 = 7
--------------------------测试满栈--------------------------
栈已满,无法进栈,最大深度 8
--------------------------循环测试出栈--------------------------
出栈元素为 ------>Person{name='姓名:7', age=7}
出栈元素为 ------>Person{name='姓名:6', age=6}
出栈元素为 ------>Person{name='姓名:5', age=5}
出栈元素为 ------>Person{name='姓名:4', age=4}
出栈元素为 ------>Person{name='姓名:3', age=3}
出栈元素为 ------>Person{name='姓名:2', age=2}
出栈元素为 ------>Person{name='姓名:1', age=1}
出栈元素为 ------>Person{name='姓名:0', age=0}
--------------------------新增栈元素测试--------------------------
栈顶元素为 ------>Person{name='测试账户', age=12}
--------------------------清空栈测试--------------------------
当前栈是否为空 ------> false
当前栈是否为空 ------> true