栈是一种先进后出的有序列表。限制元素的插入和删除只能在同一端,也即栈顶,另一端为固定的一端,被称为栈底。本文主要是介绍栈的数组实现和链表实现。
1 数组实现
使用数组实现,首先需要一个数组来存储数据,并用 maxSize 来表示该数组的大小,然后使用 top 来表示当前位于栈顶的元素的下标,当进行弹出或入栈操作的时候,就是对 top 以及它对应的元素进行处理,初始化的时候 top=-1,表示栈空。
思路比较简单,就直接上代码了。
package com.datastructure.stack;
public class ArrayStack implements MyStack {
private int maxSize; //栈容量
private int[] stack; //存放栈元素
private int top; //栈顶元素的下标
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack = new int[this.maxSize];
top = -1; //栈空时 top = -1
}
public boolean isFull() {
return top == maxSize - 1; //数组满了就是栈满了
}
public boolean isEmpty() {
return top == -1;
}
//push的时候先确定栈没有满
//然后top+1,并将新元素存放到该下标处
public void push (int value) {
if(isFull()) {
System.out.println("栈空间已满");
return;
}
top++;
stack[top] = value;
}
//先返回当前top所指的元素
//然后top-1,指向新的top元素所在位置
public int pop() {
if(isEmpty()) {
System.out.println("栈空");
throw new RuntimeException("栈空,无法弹出数据");
}
return stack[top--];
}
public void show() {
if(isEmpty()) {
System.out.println("栈空");
return;
}
for(int i=top; i>-1; --i) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
}
2 单向链表实现
将每个栈元素用数据节点表示,一个简单栈节点必须要 value 来存储值,next 来存储下一个元素。
class StackNode {
int value; //值
StackNode next; //指向下一个节点
StackNode(int value) {
this.value = value;
this.next = null;
}
}
唯一需要理清的一点就是,top 该对应链表中的哪个节点?这得看看 top 需要满足什么条件:
- 频繁的插入、删除,因此也需要快速访问到该节点;
- 从 top 节点能轻易的访问到随后的节点。
对于单向链表,在任意位置插入、删除所作的操作都是一样的,但访问速度却不一样,链表头部的节点访问速度显然更快。对于第二个条件,也是头节点才能满足。
所以我们使用一个带头节点的单向链表来实现栈,top 就是头节点,栈顶节点是 top.next
,top.next == null
时表示栈为空,这里假设栈不会满,当然也是可以设置栈大小的。
package com.datastructure.stack;
public class LinkedStack implements MyStack{
StackNode top;//top是正真top节点的前一个节点,类似于头节点
LinkedStack() {
top = new StackNode(-1);
}
//入栈
//将新节点插入到头节点后面
@Override
public void push(int value) {
if (isFull()) {
System.out.println("栈满");
return;
}
StackNode newNode = new StackNode(value);
newNode.next = top.next;
top.next = newNode;
System.out.println("新增元素:" + value);
}
//出栈
//将 top.next 指向原 top.next 的后一个节点
@Override
public int pop() {
if (isEmpty()){
System.out.println("栈空");
throw new RuntimeException("栈空,无法弹出");
}
int value = top.next.value;
top.next = top.next.next;
return value;
}
@Override
public void show() {
if(isEmpty()) {
System.out.println("栈空");
return;
}
System.out.println("当前栈为");
StackNode temp = top.next;
while (temp != null) {
System.out.println(temp.value);
temp = temp.next;
}
}
//栈空
@Override
public boolean isEmpty() {
return top.next == null;
}
//这里不设置栈大小,假设栈始终不满
@Override
public boolean isFull() {
return false;
}
}
class StackNode {
int value; //值
StackNode next; //指向下一个节点
StackNode(int value) {
this.value = value;
this.next = null;
}
}