如何基于链表/数组实现栈-算法通关村
1.栈基础知识
1.1栈的特征
- 栈和队列是比较特殊的线性表,又称之为访问受限的线性表。栈是很多表达式、符号等运算的基础,也是递归的底层实现。理论上递归能做的题目栈都可以,只是有些问题用栈会非常复杂。
- 栈底层实现仍然是链表或者顺序表,栈与线性表的最大区别是数据的存取的操作被限制了,其插入和删除操作只允许在线性表的一端进行。一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作称为入栈(Push),删除元素的操作称为出栈(Pop)。若栈中没有任何元素,则称为空栈。
1.2栈的操作
-
栈的常用操作主要有:
- push(E):增加一个元素E
- pop():弹出元素E
- peek():显示栈顶元素,但是不出栈
- empty():判断栈是否为空
-
我们在设计自己的栈的时候,不管用数组还是链表,都要实现上面几个方法。如果想测试一下自己对栈是否理解,做一下这道题就够了:入栈顺序为1234,所有可能的出栈序列是什么?
1.3Java 中的栈
-
java 的 util 中提供了栈 Stack 类。
-
public class MainTest { public static void main(String[] args) { Stack<Integer> stack = new Stack(); stack.push(1); stack.push(2); stack.push(9); System.out.println("栈顶元素为:" + stack.peek()); while(!stack.empty()){ //只显示,不出栈 System.out.println(stack.peek()); //出栈并且显示 System.out.println(stack.pop()); } } }
-
2.基于数组实现栈
-
top有的地方指向栈顶元素,有的地方指向栈顶再往上的一个空单位,本文采用指向栈顶空位置。
-
采用顺序表实现的的栈,内部以数组为基础,实现对元素的存取操作。在应用中还要注意每次入栈之前先判断栈的容量是否够用,如果不够用,可以进行扩容。
-
-
-
public class Test_Arr_Stack { public static void main(String[] args) { MyStack<String> stack = new MyStack<>(); System.out.println(stack.peek()); System.out.println(stack.isEmpty()); stack.push("java"); stack.push("is"); stack.push("beautiful"); stack.push("language"); System.out.println(stack.peek()); System.out.println(stack.isEmpty()); System.out.println(stack.pop()); System.out.println(stack.pop()); } } class MyStack<T>{ //实现栈的数组 private Object[] stack; //栈顶元素为 private int top; MyStack(){ //初始容量为10 stack = new Object[10]; } //判断是否为空 public boolean isEmpty(){ return top == 0; } //返回栈顶元素 public T peek(){ T t = null; if(top > 0){ t = (T)stack[top-1]; } return t; } //入栈 public void push(T t){ expandCapacity(top+1); stack[top] = t; top++; } //出栈 public T pop(){ T t = peek(); if(top > 0){ stack[top-1] = null; top--; } return t; } //扩大容量 public void expandCapacity(int size){ int len = stack.length; if(size > len){ size = size*3/2+1; stack = Arrays.copyOf(stack, size); } } }
-
3.基于链表实现栈
-
链栈的插入和删除都在头结点
-
-
public class Test_LinkStack { public static void main(String[] args) { LinkStack<String> stack = new LinkStack<>(); System.out.println(stack.peek()); System.out.println(stack.isEmpty()); stack.push("java"); stack.push("is"); stack.push("beautiful"); stack.push("language"); System.out.println(stack.peek()); System.out.println(stack.isEmpty()); System.out.println(stack.pop()); System.out.println(stack.pop()); } } class LinkStack<T>{ //定义链表 class LinkNode<T>{ public T data; public LinkNode next; } public LinkNode<T> head; //构造函数初始化头指针 LinkStack(){ head = null; } //判断栈是否为空 public boolean isEmpty(){ if(head == null){ return true; }else{ return false; } } //取栈顶元素 public T peek(){ if(head == null){ return null; } T t = head.data; return t; } //入栈 public void push(T t){ if(t == null){ throw new NullPointerException("参数不能为空..."); } if(head == null){ head = new LinkNode<T>(); head.data = t; head.next = null; }else{ LinkNode<T> temp = head; head = new LinkNode<T>(); head.data = t; head.next = temp; } } //出栈 public T pop(){ if(head == null){ return null; } T t = head.data; head = head.next; return t; } }
-