Java实现栈最小值移至栈顶操作时触发EmptyStackException异常
问题描述
实现Integer类型栈的操作:查找栈中的最小元素,将其移动至栈顶位置,其余元素的相对顺序保持不变。约定栈的序列最左侧元素为栈顶、最右侧元素为栈底,例如初始栈[1 2 3 4 5]经过findSmallest方法处理后,应当得到结果栈[2 3 4 5 1]。当前调用该方法后打印栈内容时,程序抛出EmptyStackException空栈异常。
原有问题代码如下:
import java.util.Scanner; import java.util.Stack; public class StackTest { public static void main(String[] args) { Scanner input = new Scanner(System.in); Stack<Integer> stack1 = new Stack<>(); for (int i = 0; i < 5; i++) { stack1.push(input.nextInt()); } System.out.println("------------------"); findSmallest(stack1); for (int i = 0; i < 5; i++) { System.out.println(stack1.pop()); } } public static void findSmallest(Stack<Integer> stack1) { Stack<Integer> stack2 = new Stack<>(); Integer min = stack1.peek(); int i = 0; while(i < 5) { if(stack1.peek() < min) min = stack1.peek(); stack2.push(stack1.pop()); i++; } int j = 0; while (j < 5) { if(!(stack2.peek().equals(min))) stack1.push(stack2.pop()); j++; } stack1.push(min); stack2.pop(); } }
错误原因
- 第二个元素转移循环逻辑有缺陷:循环固定执行5次,但仅当临时栈
stack2的栈顶元素不等于最小值时才执行弹出操作,遇到最小值时不弹出元素仅累加计数,导致循环结束后stack2中除最小值外的其余4个元素都没有移回原栈stack1,原栈仅在后续操作中压入了1个最小值元素,总元素个数只有1个。 - main方法中固定循环5次执行
pop(),原栈只有1个元素,第一次弹出后栈已为空,后续4次弹出操作直接触发EmptyStackException。 - 代码硬编码栈长度为5,通用性差,栈长度变化时会直接出现逻辑错误。
- 方法末尾多余的
stack2.pop()操作无实际业务意义,极端场景下也可能触发空栈异常。
修复后代码
修复逻辑:
- 移除硬编码的长度判断,改用栈本身的
size()方法获取元素总数,适配任意长度的栈。 - 从临时栈往原栈转移元素时,无论元素是否为最小值都先弹出临时栈,遇到最小值时标记已找到、不压入原栈,其余元素正常压入原栈,保证所有非最小值元素都能正确移回。
- 移除多余的弹出操作,所有非最小值元素转移完成后,单独把最小值压入原栈顶即可。
import java.util.Scanner; import java.util.Stack; public class StackTest { public static void main(String[] args) { Scanner input = new Scanner(System.in); Stack<Integer> stack1 = new Stack<>(); for (int i = 0; i < 5; i++) { stack1.push(input.nextInt()); } System.out.println("------------------"); findSmallest(stack1); for (int i = 0; i < 5; i++) { System.out.println(stack1.pop()); } } public static void findSmallest(Stack<Integer> stack1) { Stack<Integer> stack2 = new Stack<>(); Integer min = stack1.peek(); int stackSize = stack1.size(); // 第一次遍历:所有元素移到临时栈,同步记录最小值 for (int i = 0; i < stackSize; i++) { Integer current = stack1.pop(); if (current < min) { min = current; } stack2.push(current); } boolean minFound = false; // 第二次遍历:非最小值元素移回原栈,遇到最小值跳过压入 for (int i = 0; i < stackSize; i++) { Integer current = stack2.pop(); if (!minFound && current.equals(min)) { minFound = true; continue; } stack1.push(current); } // 最小值压入栈顶 stack1.push(min); } }
效果验证
输入序列1 2 3 4 5按顺序压入栈后,调用修复后的方法,栈的输出序列为[2, 3, 4, 5, 1],符合预期结果;执行pop打印时输出顺序为1、5、4、3、2,第一个弹出的就是栈顶的最小元素1,其余元素相对顺序保持不变。
内容的提问来源于stack exchange,提问作者ojcoding
相关产品推荐
相关产品推荐

