下压堆栈(链表实现)
前篇文章讨论了如何用数组实现一个下压栈 (能够动态调整数组大小)的方式,本文接着讨论用简单链表实现栈的方式。
由于链表这种简单的数据结构具有以下优点:
- 在头结点插入快,不受集合数据规模限制
- 在头结点删除快,同样与数据量多少无关
- 综上,插入和删除头结点元素所需时间与集合的大小无关
基于链表以上的两个优点,正好对应栈结构中的压栈和出栈操作,结合一个变量N,保存栈的元素个数,可以完美实现栈结构,代码如下:
import java.util.Iterator;
import java.util.Scanner;
/**
* @author zhangjinglong
* @date 2019-06-05-21:53
* 下压堆栈(链表实现)
*/
public class Stack<Item> implements Iterable<Item> {
private Node first;//栈顶 (最近添加的元素)
private int N; //栈中元素数量
private class Node{//定义了 经典链表实现中 结点的嵌套类
Item item;//结点中存储的数据值
Node next;//指向下个结点的链接
}
public boolean isEmpty(){//判断栈是否为空
return first==null;//Stack 对象初始化时默认为null
//也可使用 return N==0 实现
}
public int size() {return N;}
public void push(Item item){//向栈顶添加元素
Node oldfirst=first;
first=new Node();
first.item=item;
first.next=oldfirst;
N++;
}
public Item pop(){//从栈顶删除元素
Item item = first.item;
first=first.next;
N--;
return item;
}
public Iterator<Item> iterator(){
return new ListIterator();
}
private class ListIterator implements Iterator<Item>{//定义返回的迭代器
private Node current=first;//复制一份头结点引用,初始化current
public boolean hasNext(){return current.next!=null;}
public void remove(){}
public Item next(){
Item item=current.item;//保留当前指向结点的值,用以返回
current=current.next;//指向下一结点
return item;
}
}
public static void main(String[] args) {
//Stack 测试用例
//创建一个栈并根据输入的字符串指示压入或弹出字符串
Stack<String> s=new Stack<>();
Scanner scanner= new Scanner(System.in);
while(true){
if(scanner.hasNext()){
String item=scanner.next();
if(item.equals("!")){// !表示终止输入
break;
}else if( item.equals("-")){
if(s.isEmpty()){
System.out.println("the stack is empty!");
}else{
System.out.println(s.pop()+ " ");
}
}else{
s.push(item);
}
}
}
System.out.println("("+s.size()+ " left on stack)");
}
}