數據結構-棧
定義
棧(英語:stack)又稱爲堆棧或堆疊,棧作爲一種數據結構,它按照先進後出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,需要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。
由於堆疊數據結構只允許在一端進行操作,因而按照後進先出(LIFO, Last In First Out)的原理運作。棧也稱爲後進先出表
棧的應用場景
undo操作(撤銷)
-
例如:將操作的每組數據存入棧中,如果想要撤銷,只需要彈出棧頂元素,就可以恢復上一步操作了。
程序調用的系統棧
-
例如:A方法調用B方法得到返回值,B調用C得到返回值,A操作走到了B方法,這個時候可以將A的代碼位置存儲到棧中,然後走到B方法,B操作走到了C方法,這個時候可以將B的代碼位置存儲到棧中。最後C執行完成,根據棧的結構開始彈出數據,一步一步再走回A方法。
判斷括號是否有效。下文會有代碼實現(詳細規則描述可以參考leetcode第20題)
-
開括號必須用同一類型的括號閉合。
-
開方括號必須按正確順序閉合。
-
例如:正確的:{[()]} {()} 等 。錯誤的:[{(})] [}{()] 等。
自定義棧基類的代碼實現
-
棧在java.util有一個工具類,先不用,自定義實現一個
創建一個接口,用來統一規範所有棧實現
package com.datastructure.stack;
public interface Stack<E> {
/**
* 向棧插入元素
* @param e
*/
public void push(E e);
/**
* 取出最上面的元素,並且返回
* @return
*/
public E pop();
/**
* 獲取棧的大小
* @return
*/
public int getSize();
/**
* 判斷棧是否爲空
* @return
*/
public boolean isEmpty();
/**
* 獲取棧最上面的元素
* @return
*/
public E peek();
}
用基於數組的方式來實現一個棧(上篇文章數據結構-數組所寫的自定義數組)
package com.datastructure.stack;
import com.datastructure.array.Array;
/**
* @program: test
* @description:
* @author: Mr.Yang
* @create: 2019-05-02 15:27
**/
public class ArrayStack<E> implements Stack<E>{
Array<E> array;
public ArrayStack(int capacity){
array=new Array<E>(capacity);
}
public ArrayStack(){
array=new Array<E>();
}
@Override
public void push(E e) {
array.addLast(e);
}
@Override
public E pop() {
return array.removeLast();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public E peek() {
return array.getLast();
}
/**
* 獲取容量值
* @return
*/
public int getCapacity(){
return array.getCapacity();
}
@Override
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append("stack: ");
sb.append("[");
for(int i=0;i<array.getSize();i++){
sb.append(array.get(i));
if(i!=array.getSize()-1){
sb.append(", ");
}
}
sb.append("] right value is stack top");
return sb.toString();
}
}
測試代碼
package com.datastructure.stack;
/**
* @program: test
* @description:
* @author: Mr.Yang
* @create: 2019-05-02 16:11
**/
public class StackTest {
public static void main(String[] args) {
ArrayStack<Integer> integerArrayStack = new ArrayStack<>();
for(int i=0;i<5;i++){
integerArrayStack.push(i);
System.out.println(integerArrayStack);
}
Integer pop = integerArrayStack.pop();
System.out.println("----移除上級元素----value is "+pop);
System.out.println("-------------移除之後的棧打印------------------");
System.out.println(integerArrayStack);
}
}
測試結果
stack: [0] right value is stack top
stack: [0, 1] right value is stack top
stack: [0, 1, 2] right value is stack top
stack: [0, 1, 2, 3] right value is stack top
stack: [0, 1, 2, 3, 4] right value is stack top
----移除上級元素----value is 4
-------------移除之後的棧打印------------------
stack: [0, 1, 2, 3] right value is stack top
leetCode第20題,花括號正確閉合
思路
-
根據棧的數據結構特點,我們可以先將所有左括號‘[{(’放進棧中,然後判斷當前字符如果是‘)]}’這種的右括號,但是棧頂的括號卻不匹配,返回false
-
注意控制判斷
-
這裏使用java自帶的棧工具類來實現
-
leetcode給的測試例子:
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
輸入例子 | () | ()[]{} | (] | ([)] | {[]} |
代碼實現
package com.datastructure.stack;
import java.util.Stack;
/**
* @program: test
* @description:
* @author: Mr.Yang
* @create: 2019-05-02 16:59
**/
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.isValid("{\"name\": \"網站\",\"num\": 3,\"sites\": [ \"Google.com\", \"Taobao.com\", \"Waibo.wang\" ]}"));
}
public boolean isValid(String s) {
Stack<Character> characters = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '{' || c == '[' || c == '(') {
characters.push(c);
} else {
if(characters.isEmpty()){
return false;
}
Character peek = characters.pop();
switch (c) {
case '}':
if (!peek.equals('{')) {
return false;
}
continue;
case ']':
if (!peek.equals('[')) {
return false;
}
continue;
case ')':
if (!peek.equals('(')) {
return false;
}
continue;
}
}
}
return characters.isEmpty();
}
/*public boolean isValid(String s) {
Stack<Character> characters = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '{' || c == '[' || c == '(') {
characters.push(c);
} else {
if(characters.isEmpty()){
return false;
}
Character toChar = characters.pop();
if(c == ')' && toChar != '('){
return false;
}
if(c == '}' && toChar != '{'){
return false;
}
if(c == ']' && toChar != '['){
return false;
}
}
}
return characters.isEmpty();
}*/
}
如果想實現更多字符串關於括號的匹配,如JSON等等,可以根據棧的特點來實現
代碼例子GIT地址:https://github.com/tuoluofusijiyang/designPattern.git
項目簡介:這個項目是我做測試,學習的主要項目,目前裏面包含了:
-
一些設計模式的demo(抽象工程模式,適配器模式,外觀模式,命令模式,裝飾者模式等等)
-
即將學習的數據結構demo,數組,棧,後續還會持續更新數據結構,可能會有隊列,鏈表,遞歸,紅黑樹,線段樹等等一系列,如果感興趣,歡迎留言。