什么是栈
数据结构中栈的特点是先进者后出,后进者先出,对于在内存中如何存储并没有要求,如果通过数组来实现叫做顺序栈,如果通过链表实现,则叫做链式栈,可以看出上图就是顺序栈.栈只支持两个基本操作:入栈 push()和出栈 pop()。
顺序栈
因为栈的特点是先进者后出,后进者先出,所以需要一个指针记录最后入栈的数据
public class ArrayStack<E> {
private E[] items; // 数组
private int count; // 栈中元素个数
private int n; //栈的大小
// 初始化数组,申请一个大小为n的数组空间
public ArrayStack(int n) {
this.items = (E[])new Object[n];
this.n = n;
this.count = 0;
}
// 入栈操作
public boolean push(E item) {
// 数组空间不够了,直接返回false,入栈失败。
if (count == n) return false;
// 将item放到下标为count的位置,并且count加一
items[count] = item;
++count;
return true;
}
// 出栈操作
public E pop() {
// 栈为空,则直接返回null
if (count == 0) return null;
// 返回下标为count-1的数组元素,并且栈中元素个数count减一
E tmp = items[count-1];
--count;
return tmp;
}
}
链表栈
public class LinkStack<E> {
private Node top = null;
// 入栈操作
public void push(E value) {
Node newNode = new Node(value, null);
// 判断是否栈空
if (top == null) {
top = newNode;
} else {
//将后入栈的数据放到头节点
newNode.next = top;
top = newNode;
}
}
// 出栈操作
public Object pop() {
if (top == null) return -1;
E value = (E) top.data;
top = top.next;
return value;
}
// 结点
private static class Node<E> {
private E data;
private Node next;
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
public E getData() {
return data;
}
}
}
应用场景
当某些场景只涉及在某端插入和删除数据,且满足先进者后出,后进者先出时,首先要考虑栈结构
括号匹配问题
给定一个只包括
(
,)
,{
,}
,[
,]
的字符串,判断字符串是否有效。
有效字符串需满足:
1、左括号必须用相同类型的右括号闭合。
2、左括号必须以正确的顺序闭合。
示例
输入: “(]”
输出: false输入: “([)]”
输出: false输入: “{[]}”
输出: true
可以使用栈进行解决:
- 从左到右依次扫描字符串,当扫描到左括号时,则将其压入栈中
- 当扫描到右括号时,从栈顶取出一个左括号
- 如果遇到不能配对的右括号,或者栈中没有数据,则说明为非法格式
- 当所有的括号都扫描完成之后,如果栈为空,则说明合法;否则为非法格式