线性表List的延伸——栈(Stack)
栈的定义:
栈是限定在仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的那一端称为栈顶(top),另一端称为栈底(boottom)。
不含有任何元素的栈称为空栈。
栈是后进先出的线性表,简称KIFO(后进先出)表。
栈就是一个特殊的线性表,其数据元素具有线性关系。
栈是在线性表表尾进行插入和删除操作,这里的表尾是指栈顶,不是栈底。
栈的插入:进栈,也称压栈、入栈。
栈的删除:出栈,也称弹栈。
!]()
在如下图所示,当你的邮件在桌上放成一叠时,使用的就是栈的方法。当有新邮件来时,你会将它们放在最上面,当你有空时你会一封一封地从上到下阅读它们。用栈的方式存放电子邮件——在收信时将邮件压入( push)最顶端,在取信时从最顶端将它们弹出( pop),且第一封一定是最新的邮件(后进, 先出)。这种方法的好处是我们能够及时看到最新的邮件,坏处是如果你不把栈清空,某些较早的邮件可能永远也不会被阅读。再比如你打开网页中的链接是,该页面会变成一个新的页面,但是当你点击“回退”的按钮时,他会返回都到刚刚的页面。栈的后进先出策略正好能够提供你所需要的行为。当使用foreach语句迭代遍历栈中的元素时,元素的处理顺序和它们被压人入的顺序正好相反。
]()
栈的接口Stack的定义:
+int getSize() 获取栈中元素的个数
+boolean isEmpty() 判断栈是否为空
+void push(E e) 将元素e压入栈顶
+E pop() 弹栈一个元素并返回,从栈顶删除元素
+E peek() 查看当前栈顶元素
+void clear() 清空栈
代码如下:
package DS01.动态数组;
/*
线性表的一种特殊情况 栈
ArrayStack extends ArrayList,实现子类
ArrayList当做是ArraySatck的一个成员变量,我们使用的是这种
*/
public interface Stack<E> extends Iterable<E>{ //可以被迭代,继承自Iterable
//获取栈中元素的个数
int getSize();
//判断栈是否为空
boolean isEmpty();
//将元素e压入栈顶
void push(E e);
//弹栈一个元素并返回,从栈顶删除元素
E pop();
//查看当前栈顶元素
E peek();
//清空栈
void clear();
}
栈的顺序结构ArrayStack的定义
代码如下:
package DS01.动态数组;
import java.util.Iterator;
public class ArrayStack<E> implements Stack<E> {
private ArrayList<E> list;
//
public ArrayStack() {//默认无参构造函数,创建一个默认大小的栈
list = new ArrayList<>();
}
//
public ArrayStack(int capacity) {//传一个参的构造函数,创建一个容量由用户指定的顺序栈
list = new ArrayList<>(capacity);
}
@Override
public int getSize() {//存储栈的长度,栈顶位置Top必须小于该长度。
//直接调用顺序表中的方法
return list.getSize();
}
@Override
public boolean isEmpty() {//判空
return list.isEmpty();
}
@Override
public void push(E e) {//进栈从表尾进,调用addLast
list.addLast(e);
}
@Override
public E pop() {//出栈元素从表尾出,调用removeLast
return list.removeLast();
}
@Override
public E peek() {//查看当前栈顶,相当于查看表尾元素
return list.getLast();
}
@Override
public void clear() { //清空栈和清空顺序表一样,直接调用
list.clear();
}
@Override
public Iterator<E> iterator() {//迭代器也是直接调用
return list.iterator();
}
//使用toString进行打印
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("ArrayStack: %d/%d\n",getSize(),list.getCapacity()));
//用数组的形式输出
sb.append('[');
if(isEmpty()) {
sb.append(']');
}else{
for (int i = 0; i < getSize(); i++) {
sb.append(list.get(i));
if(i==getSize()-1){
sb.append(']');//遍历到最后一个元素打印']'
}else{
sb.append(','); //不然在每个元素中间打','
}
}
}
//调用对象的tostring方法返回对象
return sb.toString();
}
}
对ArrayStack类进行测试的代码:
package DS01.动态数组;
import java.util.Iterator;
public class TestArrayStack {
public static void main(String[] args) {
ArrayStack<Integer>stack = new ArrayStack<>();
System.out.println(stack);
for (int i = 1; i <=15 ; i++) {
stack.push(i);
}
System.out.println(stack);
for (int i = 1; i <=10; i++) {
stack.pop();
}
System.out.println(stack);
for(Integer i:stack) {
System.out.print(i+" ");
}
Iterator<Integer> it = stack.iterator();
while(it.hasNext()) {
System.out.print(it.next()+" ");
}
}
}