*文中内容来源于《数据结构 --Java语言描述》(第二版) 刘小晶 杜选 主编
*此系列文章作为学习记录,若文中内容有误,请大家指出,谢谢
栈(Stack)
栈的概念
栈是一种特殊的线性表,栈中的数据元素以及数据元素间逻辑关系和线性表相同,两者差别在于:线性表的插入和删除操作可以在表的任何位置进行,而栈的插入和删除操作只允许在表的尾段进行。其中,栈中允许进行插入和删除操作的一段称为栈顶(top),另一端称为栈底(bottom)。假设栈中的数据元素序列为{a0, a1, a2, …, an-1},则a0称为栈底元素,an-1称为栈顶元素,n为栈中数据元素的个数(当n = 0时,栈为空)。通常,人们将栈的插入操作称为入栈(push),而将删除操作称为出栈(pop)。
栈是一种后进先出(Last In First Out, LIFO),或先进后出(First In Last Out)的线性表。
现实中的例子,如取放一叠盘子,火车调度。
栈的抽象类型描述
public interface IStack {
public void clear(); //置空
public boolean isEmpty(); //判断是否为空
public int length(); //求栈中数据元素个数
public Object peek(); //取栈顶元素
public void push(Object x) throws Exception; //入栈
public Object pop(); //出栈
}
顺序栈的描述
/**
* 由于top指向的是栈顶元素存储位置的下一个存储单元的位置,其值就是栈顶元素在数组中
* 的存储位置编号加1(数组中位置的编号是从0开始),所以对于顺序栈的各个操作的实现,
* 只要抓住以下几个关键问题即可:
* (1)顺序栈为空的条件是top == 0;
* (2)顺序栈为满的条件是top == stackElem.length;
* (3)栈的长度为top;
* (4)栈顶元素就是以top - 1为下标的数组元素stackElem[top - 1]。
*/
import Book_U2.SqList;
public class SqStack implements IStack {
private Object[] stackElem; //对象数组
private int top; //在非空栈中,top始终指向栈顶元素的下一个存储位置,当栈为空时,top值为0
//栈的构造函数,构造一个存储空间容量为maxSize的空栈
public SqStack(int maxSize){
top = 0; //初始化top为0
stackElem = new Object[maxSize]; //为栈分配maxSize个存储单元
}
//栈置空
public void clear(){
top = 0;
}
//判断栈是否为空
public boolean isEmpty(){
return top == 0;
}
//求栈中数据元素个数
public int length(){
return top;
}
//取栈顶元素
public Object peek(){
if (!isEmpty()) //栈非空
return stackElem[top - 1];
else
return null;
}
//入栈
public void push(Object x) throws Exception{
if (top == stackElem.length) //栈满
throw new Exception("栈已满"); //抛出异常
else
stackElem[top++] = x; //先将新的数据元素x压入栈顶,再top加1
}
//出栈
public Object pop(){
if (isEmpty()) //栈空
return null;
else //栈非空
return stackElem[--top];
}
//输出栈中所有数据元素(从栈顶元素到栈底元素)
public void display(){
for (int i = top - 1; i > 0; i--)
System.out.print(stackElem[i].toString() + " "); //输出
}
}
链栈
import Book_U2.Node;
public class LinkStack implements IStack{
private Node top; //栈顶元素的引用
//将栈置空
public void clear(){
top = null;
}
//判断栈是否为空
public boolean isEmpty(){
return top == null;
}
//求栈链的长度
public int length(){
Node p = top; //初始化,p指向栈顶元素,length为计数器
int length = 0;
while(p != null){ //从栈顶元素开始先后查找,知道p指向空
p = p.next; //p指向后继结点
++length; //长度增加1
}
return length;
}
//取栈顶元素并返回其值
public Object peek(){
if (!isEmpty()) //栈非空
return top.data; //返回栈顶元素的值
else
return null;
}
//入栈
public void push(Object x){
Node p = new Node(x); //构造一个新结点
p.next = top;
top = p; //新结点成为当前的栈顶结点
}
//出栈
public Object pop(){
if (isEmpty()){
return null;
}
else{
Node p = top; //p指向被删结点(栈顶结点)
top = top.next; //修改链结点,使栈顶结点从栈顶中移出
return p.data; //返回栈顶结点的数据域的值
}
}
//输出栈中所有数据元素(从栈顶元素到栈底元素)
public void display(){
Node p = top; //初始化,p指向栈顶元素
while(p != null){ //输出所有非空结点的数据元素值
System.out.print((p.data.toString() + " "));
p = p.next; //p指针向后移
}
}
}