目录
栈概述
栈是一种数据结构,它代表只能在某一端进行插入、删除操作的特殊线性表,通常就是在线性表的尾端进行插入、删除操作。允许进行插入、删除操作的一端被称为栈顶(top),另一端则被称为栈底(bottom)。
归纳起来:栈就是一种后进先出(LIFO)的线性表。
栈常用操作:
- 初始化:通常是一个构造器,用于创建一个空栈。
- 返回栈的长度:该方法用于返回栈中数据元素的个数。
- 入栈:向栈的栈顶插入一个数据元素,栈的长度+1。
- 出栈:从栈的栈顶删除一个数据元素,栈的长度-1,该方法通常返回被删除的元素。
- 访问栈顶元素:返回栈顶的数据元素,但不删除栈顶元素。
- 判断栈是否为空:该方法判断栈是否为空,如果栈为空返回true,否则返回false。
- 清空栈:将栈清空。
顺序结构实现
顺序存储结构的栈简称为顺序栈,它利用一组地址连续的存储单元依次存放从栈底到栈顶的数据元素。
栈底位置固定不变,它的栈顶元素可以直接通过顺序栈底层数组的数组元素arr[size-1]来访问。
public class SequenceStack<T> {
private int DEFAULT_SIZE = 10;
//保存数组的长度
private int capacity;
//当数组容量不够时,每次增加的长度
private int capacityIncrement = 0;
//用数组做元素的容器
private Object[] elementData;
//栈元素的长度
private int size = 0;
public SequenceStack() {
this.capacity = DEFAULT_SIZE;
elementData = new Object[capacity];
}
public SequenceStack(T element) {
this();
elementData[0] = element;
size++;
}
/**
* 以指定长度的数组量创建栈
* @param element 第一个栈元素
* @param initSize 初始化长度
*/
public SequenceStack(T element, int initSize) {
this.capacity = initSize;
elementData = new Object[capacity];
elementData[0] = element;
size++;
}
/**
* 以指定长度的数组量创建栈
* @param element 第一个栈元素
* @param initSize 初始化长度
* @param capacityIncrement 数组增长的单位长度
*/
public SequenceStack(T element, int initSize, int capacityIncrement) {
this(element, initSize);
this.capacityIncrement = capacityIncrement;
}
//栈大小
public int length() {
return size;
}
//入栈
public void push(T element) {
ensureCapacity(size + 1);
elementData[size + 1] = element;
}
//判断当前栈空间是不是够用,不够的话以2倍扩容
private void ensureCapacity(int minCapacity) {
if (minCapacity > capacity) {
if (capacityIncrement > 0) {
while (capacity < minCapacity) {
capacity += capacityIncrement;
}
} else {
while (capacity < minCapacity) {
capacity <<= 1;
}
}
elementData = Arrays.copyOf(elementData, capacity);
}
}
//出栈
public T pop() {
T oldValue = (T) elementData[size - 1];
elementData[--size] = null;
return oldValue;
}
//返回栈顶元素,但不删除
public T peek() {
return (T) elementData[size - 1];
}
//判断是否为空
public boolean empty() {
return size == 0;
}
//清空
public void clear() {
Arrays.fill(elementData, null);
size = 0;
}
}
链表结构实现
也可采用单链表来保存栈中所有元素,这种链式结构的栈也被称为链栈。
对于链栈而言,栈顶元素不断地改变,程序只要使用一个top引用来记录当前的栈顶元素即可。
top引用变量永远引用栈顶元素,再使用一个size变量记录当前栈中包含多少元素即可。
public class LinkStack<T> {
//定义内部类Node,代表链栈的节点
private class Node {
//节点数据
private T data;
//下个节点引用
private Node next;
public Node() {
}
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
//栈顶元素
private Node top;
//链栈包含的节点数
private int size;
public LinkStack() {
top = null;
}
public LinkStack(T element) {
top = new Node(element, null);
size++;
}
public int length() {
return size;
}
//入栈
public void push(T element) {
top = new Node(element, top);
size++;
}
//出栈
public T pop() {
Node oldValue = top;
top = top.next;
oldValue.next = null;
size--;
return oldValue.data;
}
//返回栈顶元素
public T peek() {
return top.data;
}
//判断是否为空
public boolean empty() {
return size == 0;
}
//清空
public void clear() {
top = null;
size = 0;
}
}