什么是栈
栈是线性表中的一种,也被称为是访问受限的线性表,作用和数组类似,都是存储数据的一种结构。和数组不一样的是对数据的操作,以及存储数据的结构。
栈的结构
栈存储数据的原则是“先入后出”,造成这种特殊的存取数据的原则主要原因是栈的结构,如下图
图中栈顶表示是可以操作数据的一端(可以对数据进行添加和删除等操作),而栈底则表示不可操作数据的一端。而在栈中存储数据被称为入栈,读取数据被称为出栈
栈的操作
栈的常用操作有:入栈(push())、出栈(pop())、查看栈顶元素(peek())、判断栈是否为空(isEmpty())。
因此在实现栈的时候需要注意实现这几个方法
基于数组实现栈
public class ArrayStack<T> {
private Object[] arrayStack;
private int top; // 指向空
public ArrayStack() {
arrayStack = new Object[10];
}
/**
* 判断是否为空
* @return
*/
public boolean isEmpty() {
return top == 0;
}
/**
* 入栈
* @param obj
*/
public void push(T obj) {
grow(top);
arrayStack[top++] = obj;
}
/**
* 出栈
* @return 出栈元素
*/
public T pop() {
T res = peek();
if (res != null) {
top--;
}
return res;
}
public T peek() {
if (top == 0) {
return null;
}
return (T) arrayStack[top - 1];
}
/**
* 给数组扩容
* @param size 当前数组长度
*/
private void grow(int size) {
if (size >= arrayStack.length) {
size = size * 3 / 2 + 1; // 每次扩容增加 50%
arrayStack = Arrays.copyOf(arrayStack, size);
}
}
}
基于链表实现栈
在用链表实现栈的时候需要注意,入栈操作是利用链表的头插法实现的
public class LinkedStack<T> {
class Node<T> {
public T data;
public Node next;
public Node(T data) {
this.data = data;
this.next = null;
}
}
private Node<T> head;
public LinkedStack() {
}
/**
* 判断栈是否为空
* @return 布尔值
*/
public boolean isEmpty() {
return head == null;
}
/**
* 入栈
* @param data 入栈元素
*/
public void push(T data) {
Node<T> node = new Node<>(data);
if (head == null) {
head = node;
return;
}
Node curr = head;
head = node;
head.next = curr;
}
/**
* 出栈
* @return 值
*/
public T pop() {
if (isEmpty()) {
return null;
}
T res = head.data;
head = head.next;
return res;
}
/**
* 查看栈顶元素
* @return 栈顶元素值
*/
public T peek() {
if (isEmpty()) {
return null;
}
return head.data;
}
}