2.2 栈
栈是什么
栈是一种特殊的线性表。栈与线性表的不同,体现在增和删的操作。具体而言,栈的数据结点必须后进先出。后进的意思是,栈的数据新增操作只能在末端进行,不允许在栈的中间某个结点后新增数据。先出的意思是,栈的数据删除操作也只能在末端进行,不允许在栈的中间某个结点后删除数据。
也就是说,栈的数据新增和删除操作只能在这个线性表的表尾进行,即在线性表的基础上加了限制。
栈的基本操作
- 新增:通常也叫作 push 或压栈
- 删除:通常也叫作 pop 或出栈
顺序栈
栈的顺序存储可以借助数组来实现。一般来说,会把数组的首元素存在栈底,最后一个元素放在栈顶。然后定义一个 top 指针来指示栈顶元素在数组中的位置。假设栈中只有一个数据元素,则 top = 0。一般以 top 是否为 -1 来判定是否为空栈。当定义了栈的最大容量为 StackSize 时,则栈顶 top 必须小于 StackSize。
链栈
关于链式栈,就是用链表的方式对栈的表示。通常,可以把栈顶放在单链表的头部,如下图所示。由于链栈的后进先出,原来的头指针就显得毫无作用了。因此,对于链栈来说,是不需要头指针的。相反,它需要增加指向栈顶的 top 指针,这是压栈和出栈操作的重要支持。
案例
1.匹配括号
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。有效字符串需满足:左括号必须与相同类型的右括号匹配,左括号必须以正确的顺序匹配。例如,{ [ ( ) ( ) ] } 是合法的,而 { ( [ ) ] } 是非法的
解:
核心思路: 即将入栈的和栈顶的配对,如果能配上就取出栈顶的,直到栈为空,返回"合法" ,如果匹配不上,就返回"非法"
import java.util.Stack;
public class StackTest {
public static void main(String[] args) {
String s ="{[(([))]}";
System.out.println(isOk(s));
}
private static String isOk(String s) {
Stack stack = new Stack();
for(int i = 0;i < s.length(); i++) {
char curr = s.charAt(i);
//判断是否是左侧的括号,是的话就入栈
if(isLeft(curr)) {
stack.push(curr);
}else {
//如果是空的 表示第一个就是右括号,所以直接非法
if(stack.isEmpty()) {
return "非法";
}
//取出栈顶那个 判断与当前的符号是否配对
char top = (char)stack.pop();
if(!isPair(top,curr)) {
return "非法";
}
}
}
if(stack.isEmpty()) {
return "合法";
}
return "非法";
}
private static Boolean isLeft(char c) {
return c=='{'||c=='['||c=='(';
}
private static Boolean isPair(char top ,char pop) {
return top=='{'&&pop =='}'||top=='('&&pop ==')'||top=='['&&pop ==']';
}
}
2.翻转
给定一个包含 n 个元素的链表,现在要求每 k 个节点一组进行翻转,打印翻转后的链表结果。其中,k 是一个正整数,且 n 可被 k 整除,
例如,链表为 1 -> 2 -> 3 -> 4 -> 5 -> 6,k = 3,则打印 321654。我们试试用栈来解决它吧。
import java.util.Stack;
public class StackTest2 {
public static void main(String[] args) {
String s = "123456";
reverse(s, 3);
}
/**
* 将字符串 按照每k个一组翻转 利用了栈 后进先出的原理
*
* @param s
* @param k
*/
private static void reverse(String s, int k) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char element = s.charAt(i);
stack.push(element);
if (stack.size() >= k) {
while (!stack.isEmpty()) {
char c = (char) stack.pop();
System.out.print(c);
}
}
}
}
}