Java数据结构:栈
3. 栈(stack)
3.1 简介
栈只允许在有序的线性数据集合的一端(栈顶top)进行加入数据(push)和移除数据(pop)。
- 栈只能在栈顶进行push和pop操作。
- 后进先出(LIFO,Last In First Out)
- 常用一维数组或链表实现:
- 顺序栈:数组实现
- 链式栈:链表实现
- 执行复杂度:
- 访问:O(n),访问栈底(bottom)元素时
- 插入删除:O(1),只允许在顶端插入和删除
3.2 常见应用
处理只在一段插入和删除数据,并满足先进后出的特性
3.2.1 浏览器的回退和前进
使用两个栈实现。回退时将stack1的栈顶移入stack2中,前进时将stack2的栈顶返回stack1中
3.3.2 检查符号是否成对出现
给定一个只包括
'('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断该字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
比如 "()"、"()[]{}"、"{[]}" 都是有效字符串,而 "(]" 、"([)]" 则不是
public static boolean isValid(String s){
// 括号之间的对应规则
HashMap<Character, Character> mappings = new HashMap<Character, Character>();
mappings.put(')', '(');//右符号是key,左符号是value
mappings.put('}', '{');
mappings.put(']', '[');
Stack<Character> stack = new Stack<Character>();
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
//跳过其他字符
if(!mappings.containsKey(chars[i]) && !mappings.containsValue(chars[i])){
continue;
}
if (mappings.containsKey(chars[i])) {
//stack.pop()的返回值为弹出的栈顶
char topElement = stack.empty() ? '#' : stack.pop();
if (topElement != mappings.get(chars[i])) {
return false;
}
} else {
stack.push(chars[i]);
}
}
return stack.isEmpty();
}
3.2.3 反转字符串
栈中每个元素先入栈再出栈
3.2.4 维护函数调用
最后一个被调用的函数必须先完成执行,符合后进先出特性
3.3 栈的实现
该代码省去了确保容量大小和扩容的部分,在实例化对象时可以选择使用默认的大小或者自己设置容量大小。
//数组法
public class MyStack {
private int[] storage;//存放栈中元素的数组
private int capacity;//栈的容量
private int count;//栈中元素的数量
//private static final int GRO_FACTOR = 2;//扩容因子
//无初始容量,无参构造器
public MyStack() {
this.capacity = 8;
this.storage = new int[capacity];
this.count = 0;
}
//设定初始容量
public MyStack(int capacity) {
if(capacity<1){
throw new IllegalArgumentException("Capacity is too small");
}
this.capacity = capacity;
this.storage = new int[capacity];
this.count = 0;
}
//入栈
public void push(int value){
storage[count++] = value;
}
//确保容量大小
//扩容
//返回栈顶元素并出栈
public int pop(){
if(count==0){
throw new IllegalArgumentException("Stack is empty");
}
count--;
return storage[count];
}
//返回栈顶元素不出栈
public int peek(){
//return storage[count];//写错
return storage[count-1];
}
//判断栈是否为空
public boolean isEmpty(){
return count == 0;
}
//返回元素个数
public int size(){
return count;
}
}