栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶。对栈的操作有进栈(push)和出栈(pop),前者相当于插入,后者则是删除最后插入的元素。最后插入的元素可以通过使用top在执行pop之前进行考查。对空栈进行的pop或top一般被认为是栈的ADT中的错误。
栈有时又叫做LIFO(后进先出)表。如图描述的模型只象征着push是输入操作而pop和top是输出操作。普通的清空栈的操作和判断是否为空栈的测试都是栈的操作指令系统的一部分,只不过我们能做的也基本上就只有push和Pop操作。
[img]http://dl2.iteye.com/upload/attachment/0095/0528/322db1bb-a9a1-35e4-b9d3-807b4ffb9896.png[/img]
由于栈是一个表,因此任何实现表的方法都能实现栈。显然,ArrayList和LinkedList都支持栈的操作。因为栈的操作时常数时间操作,所以除非在非常独特的环境下,这是不可能产生明显改进的。
[b]
栈的链表实现[/b]
栈的第一种实现方法是使用单链表。通过在表的顶端插入来实现push,通过删除表顶端元素实现pop。top操作只是考察表顶端元素并返回值。有时Pop和top操作合二为一。
空栈异常类
[b]栈的数组实现[/b]
另一种实现方法避免的链而且可能是更流行的方式。由于模仿ArrayList的add操作,因此相应的实现方法非常简单。与每个栈相关联的操作时theArray和topOfStack,对于空栈他是-1(这就是空栈初始化做法)。为将某个元素x推入栈中,我们使topOfStack增1然后设置theArray[topOfStack]=x.为了弹出栈元素,我们设置返回值theArray[topOfStack]然后使topOfStack减1.
注意,这些操作不仅以常数时间运行,而且是以非常快的常数时间运行。
栈有时又叫做LIFO(后进先出)表。如图描述的模型只象征着push是输入操作而pop和top是输出操作。普通的清空栈的操作和判断是否为空栈的测试都是栈的操作指令系统的一部分,只不过我们能做的也基本上就只有push和Pop操作。
[img]http://dl2.iteye.com/upload/attachment/0095/0528/322db1bb-a9a1-35e4-b9d3-807b4ffb9896.png[/img]
由于栈是一个表,因此任何实现表的方法都能实现栈。显然,ArrayList和LinkedList都支持栈的操作。因为栈的操作时常数时间操作,所以除非在非常独特的环境下,这是不可能产生明显改进的。
[b]
栈的链表实现[/b]
栈的第一种实现方法是使用单链表。通过在表的顶端插入来实现push,通过删除表顶端元素实现pop。top操作只是考察表顶端元素并返回值。有时Pop和top操作合二为一。
package taxus.list;
public interface Stack {
//返回堆栈大小
public int getSize();
//判断堆栈是否为空
public boolean isEmpty();
//元素e入栈
public void push(Object e);
//栈顶元素出栈
public Object pop() throws StackEmptyException;
//获取栈顶元素
public Object peek() throws StackEmptyException;
}
空栈异常类
package taxus.list;
@SuppressWarnings("serial")
public class StackEmptyException extends Exception {
public StackEmptyException(String err){
super(err);
}
}
package taxus.list;
public class StackSLinked implements Stack {
private SLNode top; //链表首节点引用
private int size; //栈大小
public StackSLinked(){
top = null;
size = 0;
}
public int getSize() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void push(Object e) {
SLNode q = new SLNode(e, top);
top = q;
size++;
}
public Object pop() throws StackEmptyException {
if (size < 1) {
throw new StackEmptyException("Stack empty error");
}
Object o = top.getData();
top = top.getNext();
size--;
return top;
}
public Object peek() throws StackEmptyException {
if (size < 1) {
throw new StackEmptyException("Stack empty error");
}
return top.getData();
}
}
[b]栈的数组实现[/b]
另一种实现方法避免的链而且可能是更流行的方式。由于模仿ArrayList的add操作,因此相应的实现方法非常简单。与每个栈相关联的操作时theArray和topOfStack,对于空栈他是-1(这就是空栈初始化做法)。为将某个元素x推入栈中,我们使topOfStack增1然后设置theArray[topOfStack]=x.为了弹出栈元素,我们设置返回值theArray[topOfStack]然后使topOfStack减1.
注意,这些操作不仅以常数时间运行,而且是以非常快的常数时间运行。
package taxus.list;
public class StackArray implements Stack {
private final int LEN = 8; //数组初始大小
private Object[] elements; //存放数据的数组
private int top; //栈顶指针
public StackArray(){
top = -1;
elements = new Object[LEN];
}
//返回堆栈大小
public int getSize() {
return top + 1;
}
//判断堆栈是否为空
public boolean isEmpty() {
return top < 0;
}
//元素e入栈
public void push(Object e) {
if (getSize() >= elements.length) {
expandSpace();
}
elements[++top] = e;
}
private void expandSpace(){
Object[] a = new Object[elements.length * 2];
for (int i = 0; i < elements.length; i++) {
a[i] = elements[i];
}
elements = a;
}
//栈顶元素出栈
public Object pop() throws StackEmptyException {
if (getSize() < 1) {
throw new StackEmptyException("Stack empty error");
}
Object e = elements[top];
elements[top--] = null;
return e;
}
//获取栈顶元素
public Object peek() throws StackEmptyException {
if (getSize() < 1) {
throw new StackEmptyException("Stack empty error");
}
return elements[top];
}
}