「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」
Java堆栈的实现
以下实例演示了用户如何通过创建用于插入元素的自定义函数 push() 方法和用于弹出元素的 pop() 方法来实现栈:
public class MyStack {
private int maxSize;
private long[] stackArray;
private int top;
public MyStack(int s) {
maxSize = s;
stackArray = new long[maxSize];
top = -1;
}
public void push(long j) {
stackArray[++top] = j;
}
public long pop() {
return stackArray[top--];
}
public long peek() {
return stackArray[top];
}
public boolean isEmpty() {
return (top == -1);
}
public boolean isFull() {
return (top == maxSize - 1);
}
public static void main(String[] args) {
MyStack theStack = new MyStack(10);
theStack.push(10);
theStack.push(20);
theStack.push(30);
theStack.push(40);
theStack.push(50);
while (!theStack.isEmpty()) {
long value = theStack.pop();
System.out.print(value);
System.out.print(" ");
}
System.out.println("");
}
}
复制代码
以上代码运行输出结果为:
50 40 30 20 10
复制代码
顺序栈的实现
顺序栈可以通过数组存储堆栈的元素
堆栈的操作都 在栈顶完成, 选择数组中索引值较大的一端作为栈顶
/**
* 堆栈的顺序实现
* @author 老崔
*/
public class MyArrayStack implements MyStack {
private Object[] elements; //定义数组保存堆栈的元素
private static final int DEFAULT_CAPACITY = 16; //堆栈的默认容量
private int top; //栈顶指针
//在无参构造中,对数组默认初始化
public MyArrayStack() {
elements = new Object[DEFAULT_CAPACITY];
}
//在构造方法中,指定堆栈的初始化大小
public MyArrayStack(int initialCapacity) {
elements = new Object[initialCapacity];
}
// 返回元素的个数
@Override
public int getSize() {
return top;
}
// 判断堆栈是否为空
@Override
public boolean isEmpty() {
return top <= 0;
}
//入栈/压栈
@Override
public void push(Object e) {
//判断堆栈是否已满 ,如果堆栈已满 , 数组需要扩容
if ( top >= elements.length ) {
//定义一个更大的数组, 默认按2倍大小扩容
Object[] newData = new Object[elements.length * 2];
//把原来的数组的内容复制到大的数组中
for( int i = 0 ; i<elements.length; i++) {
newData[i] = elements[i];
}
//让原来的数组名指向新的数组
elements = newData;
}
//把元素存储到栈顶指针指向的位置
elements[top] = e;
//栈顶指针上移
top++;
}
// 出栈
@Override
public Object pop() {
//判断堆栈是否为空
if (top <= 0 ) {
throw new StackOverflowError("栈已空");
}
top--; //栈顶指针下移
return elements[top];
}
// 返回栈顶元素, 不删除
@Override
public Object peek() {
// 判断堆栈是否为空
if (top <= 0) {
throw new StackOverflowError("栈已空");
}
return elements[top-1];
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
// 从栈顶到栈底的顺序添加各个元素
for( int i = top-1 ; i>=0; i--) {
sb.append(elements[i]);
//元素之间使用逗号分隔
if ( i > 0 ) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
}
复制代码
链栈的实现
使用链表作为栈的存储结构, 有时也称为链栈;
栈只允许在线性表的一端进行操作, 可以选择链表的头部作为栈顶;
不管是入栈/出栈都在链表的首结点上进行。
/**
* 栈的链式存储
* @author 北京动力节点老崔
*/
public class MyLinkStack implements MyStack {
private Node top; //存储栈顶的引用
private int size; //保存堆栈中元素的个数
// 返回堆栈元素的个数
@Override
public int getSize() {
return size;
}
// 判断堆栈是否为空
@Override
public boolean isEmpty() {
return size == 0;
}
// 入栈操作
@Override
public void push(Object e) {
//根据元素生成结点,插入到链表的头部
Node pNode = new Node(e, top);
//修改top栈顶指针指向新的结点
top = pNode;
size++;
}
// 出栈
@Override
public Object pop() {
//先判断堆栈是否为空
if (size < 1 ) {
throw new StackOverflowError("栈已空");
}
Object oldData = top.data; //保存原来栈顶元素
top = top.next; //栈顶指针后移
size--;
return oldData;
}
// 返回栈顶元素
@Override
public Object peek() {
// 先判断堆栈是否为空
if (size < 1) {
throw new StackOverflowError("栈已空");
}
return top.data;
}
@Override
public String toString() {
// 把链表中各个结点的数据给返回
StringBuilder sb = new StringBuilder();
sb.append("[");
for( Node pNode = top; pNode!=null; pNode= pNode.next) {
sb.append(pNode.data);
//数据元素之间使用逗号分隔
if ( pNode.next != null) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
//定义一个内部类,描述 链表中的结点
private class Node{
Object data; //存储数据
Node next; //存储下个结点的引用
public Node(Object data, Node next) {
super();
this.data = data;
this.next = next;
}
}
}
复制代码