栈的主要特点是“后进先出”,即后进栈的元素先被处理。因此,栈又被称为后进先出(last in first out,LIFO)表。它的实现方式主要有顺序栈、链表栈两种。
首先使用接口定义栈的几个方法
public interface StackADT<T> {
/**
* 压入栈中一个元素
*
* @param element
*/
public void push(T element);
/**
* 弹出栈中一个元素
*
* @return
*/
public T pop();
/**
* 查看栈顶的元素
*
* @return
*/
public T peek();
public boolean isEmpty();
public int size();
public String toString();
}
再定义一个异常处理,当栈中元素为空时,弹出栈报此异常
public class EmptyCollectionException extends RuntimeException {
public EmptyCollectionException(String collection){
super("The "+collection+" is empty.");
}
}
顺序栈
实现代码
public class ArrayStack<T> implements StackADT<T> {
private int DEFAULT_SIZE = 5;
private int capacity;
private int top;//该变量为紧跟栈顶元素后的数组索引号,也是栈目前的容量,top-1为栈顶的索引,
private T[] stack;
public ArrayStack() {
capacity = DEFAULT_SIZE;
top = 0;
stack = (T[]) (new Object[capacity]);
}
public ArrayStack(int initCapity) {
top = 0;
capacity = initCapity;
stack = (T[]) (new Object[capacity]);
}
/**
* 实现步骤:
* 1、确保该数组不是满的
* 2、把数组top引用设置为要加入栈中的对象
* 3、增加top的值
*
* @param element
*/
@Override
public void push(T element) {
if (capacity == stack.length) {
expandCapacity();
}
stack[top] = element;
top++;
}
/**
* 实现步骤:
* 1、确保栈不为空
* 2、减小top的计数
* 3、设置一个临时引用等于stack[top]的元素
* 4、设置stack[top]为空
* 5、返回该临时引用
*
* @return
* @throws EmptyStackException
*/
@Override
public T pop() throws EmptyStackException {
if (isEmpty()) {
throw new EmptyCollectionException("ArrayStack");
}
top--;
T result = stack[top];
stack[top] = null;
return result;
}
@Override
public T peek() {
if (isEmpty()) {
throw new EmptyCollectionException("ArrayStack");
}
return stack[top - 1];
}
@Override
public boolean isEmpty() {
if (top == 0) {
return true;
}
return false;
}
@Override
public int size() {
return top;
}
@Override
public String toString() {
if (top == 0) {
return "{}";
} else {
StringBuilder sb = new StringBuilder("{");
for (int i = size() - 1; i >= 0; i--) {
if (stack[i] != null) {
if (i != 0) {
sb.append(stack[i].toString() + ";");
} else {
sb.append(stack[i].toString());
}
}
}
int len = sb.length();
return sb.append("}").toString();
}
}
/**
* 扩容数组
*/
private void expandCapacity() {
stack = Arrays.copyOf(stack, stack.length * 2);
}
}
编写测试顺序栈
public class TestArrayStack {
public static void main(String[] args) {
ArrayStack<Integer> arrayStack = new ArrayStack<>();
arrayStack.push(123);
arrayStack.push(13);
arrayStack.push(15);
arrayStack.push(16);
arrayStack.push(18);
System.out.println(arrayStack);
ArrayStack<Integer> invertStack = new ArrayStack<>();//反转栈
int length = arrayStack.size();
for (int i = 0; i <length; i++) {
invertStack.push(arrayStack.pop());
}
System.out.println(invertStack);
System.out.println(arrayStack.size());
}
}
输出结果
{18;16;15;13;123}
{123;13;15;16;18}
0
链表栈
首先建一个结点类LinearNode
public class LinearNode<T> {
private T element;
private LinearNode<T> next;
public LinearNode() {
element = null;
next = null;
}
public LinearNode(T element) {
this.element = element;
next = null;
}
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public LinearNode<T> getNext() {
return next;
}
public void setNext(LinearNode<T> next) {
this.next = next;
}
}
实现代码
public class LinkedStack<T> implements StackADT<T> {
private int count;
private LinearNode<T> top;
public LinkedStack() {
count = 0;
top = null;
}
/**
* 实现步骤:
* 1、创建一个新结点,该结点含有一个引用,指向要放置到栈中的对象
* 2、把新结点的next引用设置为指向当前栈顶(如果为空,那它就是null)
* 3、把top引用设置为指向该新结点
* 4、递增栈的元素计数
*
* @param element
*/
@Override
public void push(T element) {
LinearNode<T> temp = new LinearNode<>(element);
temp.setNext(top);
top = temp;
count++;
}
/**
* 实现步骤:
* 1、确保栈不为空
* 2、设置一个临时引用等于栈顶元素
* 3、设置top引用等于栈顶结点的next引用
* 4、递减栈的元素计数
*
* @return
*/
@Override
public T pop() {
if (isEmpty()) {
throw new EmptyCollectionException("ArrayStack");
}
T result = top.getElement();
top = top.getNext();
count--;
return result;
}
@Override
public T peek() {
return top.getElement();
}
@Override
public boolean isEmpty() {
if (count == 0) {
return true;
}
return false;
}
@Override
public int size() {
return count;
}
@Override
public String toString() {
if (count == 0) {
return "{}";
} else {
StringBuilder sb = new StringBuilder("{");
LinearNode<T> current = top;
for (int i = size() - 1; i >= 0; i--) {
if (current.getElement() != null) {
if (i != 0) {
sb.append(current.getElement().toString() + ";");
} else {
sb.append(current.getElement().toString());
}
}
current = current.getNext();
}
int len = sb.length();
return sb.append("}").toString();
}
}
}
测试代码
public class TestLinkStack {
public static void main(String[] args) {
LinkedStack<Integer> arrayStack = new LinkedStack<>();
arrayStack.push(123);
arrayStack.push(13);
arrayStack.push(15);
arrayStack.push(16);
arrayStack.push(18);
System.out.println(arrayStack);
LinkedStack<Integer> invertStack = new LinkedStack<>();//反转
int length = arrayStack.size();
for (int i = 0; i <length; i++) {
invertStack.push(arrayStack.pop());
}
System.out.println(invertStack);
System.out.println(invertStack.size());
}
}
运行结果
{18;16;15;13;123}
{123;13;15;16;18}
5
顺序栈、链表栈对比