栈(stack),它是一种运算受限的线性表,后进先出(LIFO)
- LIFO(last in first out)表示就是后进入的元素, 第一个弹出栈空间. 类似于自动餐托盘, 最后放上的托盘,
往往先把拿出去使用. - 其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。
- 向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;
- 从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
- 时间复杂度:出/入栈O(1),扩容O(n)
栈的分类:
可以基于数组、单向链表实现。两者区别跟数组和链表一样。
public interface MyStack<Item> {
MyStack<Item> push(Item item);
Item pop();
int size();
boolean isEmpty();
}
public class ArrayStack<Item> implements MyStack<Item>{
private Item [] a;
public int n = 0;
public ArrayStack(int cap){
a = (Item[]) new Object[cap];
}
/**
* 2被扩容
*/
private void judgeSize(){
if(n >= a.length ){
resize(a.length * 2);
}
}
/**
* 扩容
* @param size
*/
private void resize(int size){
Item [] temp = (Item[]) new Object[size];
for (int i = 0; i < n; i++) {
temp[i] = a[i];
}
a = temp;
}
/**
* 收缩
*/
private void shrink(){
if(n > 0 && n <= a.length / 2){
resize( a.length / 2);
}
}
@Override
public MyStack push(Item item) {
judgeSize();
a[n++] = item;
return null;
}
@Override
public Item pop() {
if(isEmpty()){
return null;
}
Item item =a[--n];
a[n] = null;
shrink();
return item;
}
@Override
public int size() {
return n;
}
@Override
public boolean isEmpty() {
return n== 0;
}
public static void main(String[] args) {
ArrayStack arrayStack = new ArrayStack(4);
arrayStack.push("1");
arrayStack.push("2");
arrayStack.push("3");
arrayStack.push("4");
arrayStack.push("5");
System.out.println(arrayStack.size());
arrayStack.pop();
arrayStack.pop();
arrayStack.pop();
System.out.println(arrayStack.size());
}
}
拓展应用:
1、基于栈,实现符号匹配:时间复杂度O(n)
public class KuoHaoStack {
public static boolean isOk(String s){
ArrayStack<Character> brackes = new ArrayStack<>(50);
char[] c = s.toCharArray();
Character top;
for (char c1 : c) {
switch (c1) {
case '{':
case '(':
case '[':
brackes.push(c1);
break;
case '}':
top = brackes.pop();
if(top!= null && top == '{'){
break;
} else {
return false;
}
case ')':
top = brackes.pop();
if(top!= null && top == '('){
break;
} else {
return false;
}
case ']':
top = brackes.pop();
if(top!= null && top == '['){
break;
} else {
return false;
}
default:
break;
}
}
return brackes.isEmpty();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
System.out.println("匹配结果:"+isOk(scanner.next()));
}
}
}
2、基于栈,实现简单的四则运算:
1、声明 两个栈,一个存数字,一个存运算符
2、遇到数字,直接入栈到数字栈里面
3、遇到符号就把符号栈的栈顶拿出来做比较,如果它比栈顶符号的优先级高就直接入栈。如果比符号栈顶的优先级低或者相等,就从符号栈顶里面取栈顶(数字栈中取栈顶的两个数)进行计算。计算完把新的计算术插入栈顶。举例:1+3*4-5=8
3、java 函数调用:a调a中的b方法,b又调b中的c 方法。最后一次返回为c->b->a。
4、浏览器的前进和后退:两个栈A,B 点击前进入A栈,点后退出A栈入B栈。点前进出B栈入A栈。