什么是栈:
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何元素的栈称为空栈。栈又被称为后进先出(last in first out)的线性表,简称LIFO。
栈的基本操作:
push(Object obj):入栈操作
pop():出栈操作
peek():获得栈顶元素
顺序栈:
栈的结构图如下所示:
顺序栈的代码实现实例如下:
数组实现栈方式一 :数组长度固定
优点:入栈出栈速度快均为O(1)
缺点:栈的大小是一定的
package stack; /** * 用数组来实现栈的操作一 * 优点:入栈和出栈的速度快 * 缺点:栈的长度是有限的 * */ public class Stack { private int top = -1; private static Object[] objs; public Stack(int capacity) throws Exception{ if(capacity < 0) throw new Exception("初始值不正确:"+capacity); objs = new Object[capacity]; } //栈的大小 public int size(){ return top; } //判断栈是否为空 public boolean isEmpty(){ if(top == -1){ return true; }else{ return false; } } //入栈 public void push(Object obj) throws Exception{ if(top == objs.length - 1) throw new Exception("栈已经满了!"); top ++; objs[top] = obj; } //出栈 public Object pop() throws Exception{ if(this.isEmpty()) throw new Exception("栈为空!"); Object result = objs[top]; objs[top] = null; top --; return result; } //获取栈顶元素 public Object peek() throws Exception{ if(this.isEmpty()){ throw new Exception("栈为空!"); } Object result = objs[top]; return result; } public void display(){ System.out.print("从栈底到栈顶的元素依次为:"); for(int i=0; i<=top; i++){ System.out.print(objs[i]+" "); } System.out.println("\n"); } public static void main(String[] args) throws Exception { Stack s = new Stack(5); s.push("A"); s.push("B"); s.push("C"); s.display(); System.out.println("删除的元素为:"+s.pop()); System.out.println("栈顶的元素为:"+s.peek()); s.display(); } }数组实现方式二:数组的长度可以扩展
优点:没有长度限制
缺点:入栈出栈的时候速度比较慢出栈的时间并没有影响为O(1),而入栈的时间由于需要数组的扩容,再要将原数组的元素考入新数组,所以时间有可能为O(n)。
package stack; import java.util.Arrays; /** * 数组实现栈的操作二: * 优点:无长度限制 * 缺点:入栈和出栈的速度慢 * */ public class UnboundedStack { private int top = -1; private Object[] objs; public UnboundedStack() throws Exception{ this(10); } public UnboundedStack(int capacity) throws Exception{ if(capacity < 0) throw new Exception("Illeagal capacity:"+capacity); objs = new Object[capacity]; } public int size(){ return top; } public boolean isEmpty(){ if(top == -1){ return true; }else{ return false; } } public void push(Object obj){ if(top == objs.length-1){ this.enlarge(); } top ++; objs[top] = obj; } public Object pop() throws Exception{ if(this.isEmpty()) throw new Exception("Stack is Empty!"); Object result = objs[top]; objs[top] = null; top --; return result; } private void enlarge(){ int num = objs.length/3; if(num == 0) num = 1; objs = Arrays.copyOf(objs, objs.length+num); } public Object peek() throws Exception{ if(this.isEmpty()){ throw new Exception("栈为空!"); } Object result = objs[top]; return result; } public void display(){ System.out.print("从栈底到栈顶的元素依次为:"); for(int i=0; i<=top; i++){ System.out.print(objs[i]+" "); } } public static void main(String[] args) throws Exception { UnboundedStack us = new UnboundedStack(2); us.push("A"); us.push("B"); System.out.println("栈顶元素为:"+us.peek()); us.display(); System.out.println("删除的元素为:"+us.pop()); us.display(); us.push("C"); us.push("D"); System.out.println("栈顶元素为:"+us.peek()); us.display(); } }
栈的链式存储结构:
入栈与出栈的结构图:
入栈:把当前元素赋值给新节点的直接后继,将新节点赋值为栈顶元素。data.next = top; top = data;
出栈:将栈顶指针向下移动以为即可。Data temp = top; top = first.next;
具体代码示例如下:
链表的方式实现栈:无长度的限制,插入和删除的时间复杂度均为O(1)
package stack; /** * 单链表的形式实现栈: * 优点:长度不固定,插入删除的速度都为O(1) * */ public class LinkListStack { private class Data{ private Object obj; private Data next = null; Data(Object obj){ this.obj = obj; } } private Data top = null; //使用头插法进栈 public void push(Object obj){ Data data = new Data(obj); data.next = top; top = data; } public Object pop() throws Exception{ if(top == null) throw new Exception("empty!"); Data temp = top; top = top.next; return temp.obj; } public Object peek() throws Exception{ if(top == null){ throw new Exception("empty!"); } return top.obj; } public void display(){ if(top == null) System.out.println("empty"); System.out.print("从栈顶到栈底的元素依次为:"); Data data = top; while(data != null){ System.out.print(data.obj.toString()+" "); data = data.next; } System.out.println("\n"); } public static void main(String[] args) throws Exception { LinkListStack ll = new LinkListStack(); ll.push("A"); ll.push("B"); ll.push("C"); System.out.println("栈顶的元素为:"+ll.peek()); ll.display(); System.out.println("删除的元素为:"+ll.pop()); ll.display(); } }