Stack_Queue 固定容量的栈组SetOfStacks @CareerCup
来源:互联网 发布:在线算法测试网站 编辑:程序博客网 时间:2024/06/05 20:45
原文:
Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in real life, we would likely start a new stack when the previous stack exceeds some threshold. Implement a data structure SetOfStacks that mimics this. SetOfStacks should be composed of several stacks, and should create a new stack once the previous one exceeds capacity. SetOfStacks.push() and SetOfStacks.pop() should behave identically to a single stack (that is, pop() should return the same values as it would if there were just a single stack).
FOLLOW UP
Implement a function popAt(int index) which performs a pop operation on a specific sub-stack.
译文:
栈就像叠盘子,当盘子叠得太高时,就会倾斜倒下。因此,在真实的世界中,当一叠盘子 (栈)超过了一定的高度时,我们就会另起一堆,再从头叠起。实现数据结构SetOfStacks 来模拟这种情况。SetOfStacks由几个栈组成,当前一栈超出容量时,需要创建一个新的栈 来存放数据。SetOfStacks.push()和SetOfStacks.pop()的行为应当和只有一个栈时 表现的一样。
进一步地,
实现函数popAt(int index)在指定的子栈上进行pop操作。
思路:
我们要设计自己的栈(Stack),栈节点(Node)。然后用一个ArrayList<Stack>来构成栈组SetOfStacks。
我们的栈里面的节点以链表方式存储最佳,因为我们要频繁对栈顶栈底元素操作,如果用array将会导致大量的元素移动。所以我们用链表方式存储栈内的节点,同时对每个栈,我们还维护一个capacity的变量,用来track当前栈内元素个数!
因此,就不难理解Node类的数据结构,Stack类中比较有意思的是join,相当于连接两个节点,在每push进一个新元素时,新元素都要和旧的栈顶元素做join。还有一个函数叫做removeBottom,并不expose给user调用,而是在SetOfStacks的leftShift函数中会用到。
至于SetOfStacks类,有一个原则就是,压入的新元素总是被压倒最后一个栈,这样能保证前面的栈都是满的!所以没有pushAt函数,但是我们支持popAt函数,就是制定在某个栈上pop,当某个栈(除了最后一个栈)被pop掉栈顶元素,那么那个栈就不是满的了,所以我们要递归地从下一个栈,把它的栈底元素移到当前栈。这就需要用到leftShift函数。具体步骤可参考代码,已经详细注释!
这样我们就封装好了SetOfStacks类,也是用户唯一能看到的类。
package Stack_Queue;import java.util.ArrayList;public class S3_3 {//=================================== Node 自定义栈节点,以链表节点方式存在static class Node {public Node above;public Node below;public int value;public Node (int value) {this.value = value;}}//=================================== Stack 自定义的Stack类,以链表方式存储数据!static class Stack {private int capacity;public Node top;public Node bottom;public int size = 0;public Stack(int capacity) {this.capacity = capacity;}// 判断stack是否满了public boolean isFull() {return size == capacity;}// 判断stack是否为空public boolean isEmpty() {return size == 0;}// 让栈内的两个元素产生关联public void join(Node above, Node below) {if(below != null) {below.above = above;}if(above != null) {above.below = below;}}// 压入一个元素public boolean push(int val) {if(size >= capacity) {return false;}size++;Node newNode = new Node(val);if(size == 1) {// 该初始化bottom的情况bottom = newNode;}join(newNode, top);// 把newNode放在原top的上面top = newNode;// 更新栈顶指针return true;}// 弹栈public int pop() {Node ret = top;top = top.below;// 更新栈顶指针size--;// 更新栈sizereturn ret.value;}// 移除栈底元素,返回被移除的值public int removeBottom() {Node ret = bottom;bottom = bottom.above;if(bottom != null) {bottom.below = null;}size--;return ret.value;}}//=================================== SetOfStacks 栈组static class SetOfStacks {ArrayList<Stack> stacks = new ArrayList<Stack>();public int capacity;public SetOfStacks(int capacity) {this.capacity = capacity;}// 从stacks中得到最后一个Stackpublic Stack getLastStack() {if(stacks.size() == 0) {return null;}return stacks.get(stacks.size() - 1);}// 把元素压入SetOfStackspublic void push(int val) {Stack last = getLastStack();if(last != null && !last.isFull()) {last.push(val);} else{// 最后一个stack已经满了,或者stacks为空,必须新建最后一个stackStack stack = new Stack(capacity);stack.push(val);stacks.add(stack);}}// 从SetOfStacks中弹栈public int pop() {Stack last = getLastStack();int val = last.pop();if(last.size == 0) {// 如果最后一个栈空了,就从stacks中移除stacks.remove(stacks.size()-1);}return val;}// 在第index个栈上弹栈public int popAt(int index) {return leftShift(index, true);}// 一个重要的辅助函数,移除当前栈顶元素,并利用递归移动下一个栈底元素到当前栈顶public int leftShift(int index, boolean removeTop) {Stack stack = stacks.get(index);int removedItem;if(removeTop) {removedItem = stack.pop();} else {removedItem = stack.removeBottom();}if(stack.isEmpty()) {stacks.remove(index);} else if(index+1 < stacks.size()) {// 确保有下一个栈,否则证明现在的栈已经是最后一个栈了!// 把下一个栈的栈底元素移到当前栈的栈顶,这样能保证除了最后一个栈,其他栈都是满的!int v = leftShift(index+1, false);stack.push(v);}return removedItem;}// 查看SetOfStacks栈组是否为空,只要看最后一个栈是否为空即可public boolean isEmpty() {Stack last = getLastStack();return last==null || last.isEmpty();}}public static void main(String[] args) {int capacity_per_substack = 5;SetOfStacks set = new SetOfStacks(capacity_per_substack);for (int i = 0; i < 34; i++) {set.push(i);}for (int i = 0; i < 34; i++) {System.out.println("Popped " + set.pop());}}}
- Stack_Queue 固定容量的栈组SetOfStacks @CareerCup
- Stack_Queue 一个数组实现三个栈 @CareerCup
- Stack_Queue 栈实现min函数 @CareerCup
- Stack_Queue 两个栈实现一个队列 @CareerCup
- Stack_Queue 把栈排序 Sort a stack @CareerCup
- Stack_Queue 汉诺塔Hanoi问题 @CareerCup
- 数据结构--容量固定的数组
- Stack_Queue 猫狗队列问题 Cat dog queue @CareerCup
- 数据结构【一】数组实现固定容量字符串栈
- 栈队列练习——堆盘子SetOfStacks
- LinkedHashMap实现一个固定容量的基于最近最少使用算法的缓存类
- 改设置里存储的flash总容量为固定值
- 堆盘子SetOfStacks
- Q.3.3 SetOfStacks
- 输入固定组的字符串
- 【C语言】通讯录管理系统(容量固定)
- Recursion n对括号的组合 @CareerCup
- Recursion 计算表达式的括号组合 @CareerCup
- SQL SERVER中LEAD和LAG函数
- SQL SERVER中FIRST_VALUE和LAST_VALUE
- SQL SERVER中PERCENTILE_CONT和PERCENTILE_DISC
- SQL SERVER中GROUPING SETS,CUBE,ROLLUP
- SQL SERVER中XML查询:FOR XML指定RAW
- Stack_Queue 固定容量的栈组SetOfStacks @CareerCup
- 循环不变性(loop invariant)-证明算法的正确性的一种方法
- SQL SERVER中XML查询:FOR XML指定AUTO
- SQL SERVER中XML查询:FOR XML指定EXPLICIT
- SQL SERVER中XML查询:FOR XML指定PATH
- 一个hello程序的android内核模块编译方法及在模拟器中进行测试结论
- all kinds of containers
- Stack_Queue 汉诺塔Hanoi问题 @CareerCup
- 非官方的结合国际快递和规定非结构化的健康