栈是一种先进后出的数据结构,在实际编程栈有很广泛的用处,Java栈已经帮我们实现好了stack类。
实现栈的两种方式,基于数组实现和基于链表实现。
1.stack接口
public interface StackADT {
//入栈操作
public void push(Object element);
//出栈操作
public Object pop();
//判断是否为空
public boolean isEmpty();
//得到当前栈的大小
public int size();
//返回栈顶对象的引用
public Object peek();
//转化为字符串
public String toString();
}
//基于数组实现栈stack 类栈维护一个数组、一个top指针即可
public class ArrayStack implements StackADT {
//用数组来存储压入栈的对象
private Object[] contents;
//标记当前栈的栈顶元素
private int top;
//默认数组大小
private static int SIZE=10;
//构造函数初始化
public ArrayStack() {
contents=new Object[SIZE];
top=0;
}
//基于数组实现,必须有一个扩容方法,当栈不够大时,进行扩容
//扩容的本质就是新建一个两倍大的数组,之前的数组丢掉不要
public void expand(){
//每次将当前size扩大为两倍
Object[] larger=new Object[size()*2];
for(int index=0;index<top;index++)
larger[index]=contents[index];
//将指向数组的引用指向新的扩容后的数组,旧的数组没有引用指向就会被垃圾回收器回收
contents=larger;
}
@Override
public void push(Object element) {
if(top==contents.length)
expand();
contents[top]=element;
top++;
}
@Override
public Object pop() {
if(isEmpty()){
System.out.println("stack is empty");
System.exit(1);
}
Object result = contents[top-1];
contents[top-1] = null;//出栈 即把栈顶元素的引用置为null,实际上元素对象还在,被另一个result引用所指
top--;
return result;
}
@Override
public boolean isEmpty() {
return (size()==0);
}
@Override
public int size() {
return top;
}
@Override
public Object peek() {
Object result;
if(isEmpty())
result = null;
else
result = contents[top-1];
return result;
}
public static void main(String[] args) {
ArrayStack stack = new ArrayStack();
System.out.println("将0到24依次压栈,然后连续10次出栈");
for(int i = 0;i < 25;i++)
stack.push(i);
for(int i = 0;i < 10;i++)
stack.pop();
System.out.println("栈的大小为: " + stack.size());
System.out.println("栈为空吗?: " + stack.isEmpty());
System.out.println("栈顶元素为: " + stack.peek());
}
}
//基于链表实现栈,也就是以节点的形式存储栈,从头节点往外取出数据,这样好处理
public class LinkedStack implements StackADT {
// 链表节点类,内部类实现,包含数据域和指针域
class Node {
int data; // 数据域
Node next;// 指针域
public Node(int data) {
this.data = data;
}
}
private Node top;
private int count;
public LinkedStack(){
top = null;
count = 0;
}
@Override
public void push(Object element) {
Node node=new Node((Integer)element);
//倒序构造链表,最先入栈的是链表尾部,然后最后入栈的是链表头部,这样指针指向关系容易实现,虽然逻辑不好理解
//因为我们的理解一般是从头部开始构造节点,而从尾部开始构造节点比较抽象
node.next=top;
//指向的是头结点
top=node;
count++;
}
@Override
public Object pop() {
if(isEmpty()){
System.out.println("stack is empty!");
System.exit(1);
}
Object result=top.data;
top=top.next;
count--;
return result;
}
@Override
public boolean isEmpty() {
return (size()==0);
}
@Override
public int size() {
return count;
}
@Override
public Object peek() {
Object result = top.data;
return result;
}
}