概念
栈是一种线性结构,相比数组,栈对应的操作是数组的子集,只能从一端添加元素,也只能从一端取出元素,这一端称为栈顶.
特点
栈是一种先进后出(后进先出)的数据结构.
数组栈实现
public interface Stack<E> {/*** 获取栈中元素个数** 时间复杂度 O(1)* @return int*/int getSize();/*** 判断栈是否为空** 时间复杂度 O(1)* @return boolean*/boolean isEmpty();/*** 在栈中添加元素e(入栈)** 时间复杂度 O(1)均摊* @param e 元素*/void push(E e);/*** 从栈中取出元素(出栈)** 时间复杂度 O(1)均摊* @return E*/E pop();/*** 查看栈顶元素** 时间复杂度 O(1)* @return E*/E peek();}
注意:这里的Array类是前面动态数组实现的Array类,点击动态数组跳转:
public class ArrayStack<E> implements Stack<E> {Array<E> array;public ArrayStack(int capacity) {array = new Array<>(capacity);}public ArrayStack() {array = new Array<>();}@Overridepublic int getSize() {return array.getSize();}@Overridepublic boolean isEmpty() {return array.isEmpty();}public int getCapacity() {return array.getCapacity();}@Overridepublic void push(E e) {//在数组末尾添加元素array.addLast(e);}@Overridepublic E pop() {return array.removeLast();}@Overridepublic E peek() {return array.getLast();}@Overridepublic String toString() {StringBuilder builder = new StringBuilder();builder.append("Stack: ");builder.append("[");for (int i = 0; i < array.getSize(); i++) {builder.append(array.get(i));if (i != array.getSize() - 1) {builder.append(",");}}builder.append("] top");return builder.toString();}public static void main(String[] args) {ArrayStack<Integer> stack = new ArrayStack<>();for (int i = 0; i < 5; i++) {//入栈stack.push(i);System.out.println(stack);}//出栈stack.pop();System.out.println(stack);}}
栈的应用
有效的括号(leetcode20题):
1. 要求:
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。<br />有效字符串需满足:<br />左括号必须用相同类型的右括号闭合。<br />左括号必须以正确的顺序闭合。
2. 使用Java的Stack实现:
public static boolean isValid(String s) {Stack<Character> stack = new Stack<>();for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);if (c == '(' || c == '[' || c == '{') {//将左括号全部放入栈中stack.push(c);} else {if (stack.isEmpty()) {return false;}//删除栈顶元素并返回栈顶元素char topChar = stack.pop();if (c == ')' && topChar != '(') {return false;}if (c == ']' && topChar != '[') {return false;}if (c == '}' && topChar != '{') {return false;}}}return stack.isEmpty();}
3.使用Java的Stack结合Map实现:
public static boolean isValid2(String s) {int n = s.length();//当括号成对时必然是偶数,若不为偶数可直接返回falseif (n % 2 == 1) {return false;}Map<Character, Character> pairs = new HashMap<Character, Character>() {{put(')', '(');put(']', '[');put('}', '{');}};Deque<Character> stack = new LinkedList<Character>();for (int i = 0; i < n; i++) {char ch = s.charAt(i);//当元素是右括号时,删除栈顶元素使用返回的被删除的栈顶元素判断是否等于当前key元素的value值,不等直接返回falseif (pairs.containsKey(ch)) {if (stack.isEmpty() || !stack.pop().equals(pairs.get(ch))) {return false;}} else {//当元素是左括号时存入栈中stack.push(ch);}}//循环完毕,判断栈中是否还有元素,若没有元素则为turereturn stack.isEmpty();}
4.使用go结合Map实现:
与Java版本Map实现方式思路一致
func isValid(s string) bool {n := len(s)if n%2 == 1 {return false}pairs := map[byte]byte{')': '(',']': '[','}': '{',}var stack []bytefor i := 0; i < n; i++ {if pairs[s[i]] > 0 {if len(stack) == 0 || stack[len(stack)-1] != pairs[s[i]] {return false}stack = stack[:len(stack)-1]} else {stack = append(stack, s[i])}}return len(stack) == 0}
5.使用go不结合Map实现
与java版本的不结合map实现思路一致
func isValid2(s string) bool {var stack []bytefor i := 0; i < len(s); i++ {c := s[i]if c == '(' || c == '[' || c == '{' {stack = append(stack, c)} else {if len(stack) == 0 {return false}topChar := stack[len(stack)-1]if c == ')' && topChar != '(' {return false}if c == ']' && topChar != '[' {return false}if c == '}' && topChar != '{' {return false}stack = stack[:len(stack)-1]}}return len(stack) == 0}
6.使用上面自己实现的ArrayStack数组栈实现:
public static boolean isValid3(String s){ArrayStack<Character> stack = new ArrayStack<>();for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);if (c == '(' || c == '[' || c == '{') {//将左括号全部放入栈中stack.push(c);} else {if (stack.isEmpty()) {return false;}//删除栈顶元素并返回栈顶元素char topChar = stack.pop();if (c == ')' && topChar != '(') {return false;}if (c == ']' && topChar != '[') {return false;}if (c == '}' && topChar != '{') {return false;}}}return stack.isEmpty();}
