原文:
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操作。
首先当不考虑进一步的操作,popAt(int index)时。 单纯考虑入栈出栈操作。每个子栈用相等长度数组存储栈元素,当一个栈数组存满元素,则记录下一个栈
可以使用变量curStack 记录当前所在栈编号。
如果元素入栈,首先判断整个栈是否满栈,当整个栈满栈,则提示栈满。
/**
* 是否栈满
* 栈满条件为子栈为最大且同时也满栈
* @return
*/
public boolean isFull() {
return curStack == (childStack-1) && stack[curStack].isFull();
}
否则入栈,入栈则需要先判断当前子栈是否已经满栈,如果当前子栈已经满栈,则curStack++。进入下一个子栈,如果当前子栈不满栈,则元素入栈stack[curStack].push(data);
如果元素出栈,则首先判断是否整个栈栈空,栈空则提示栈空。
/**
* 是否栈空
* 栈空条件为子栈是否最小且同时为空
* @return
*/
public boolean isEmpty() {
return curStack == 0 && stack[curStack].isEmpty();
}
如果栈不空,则出栈,如果子栈为空,则curStack--进入前一个子栈获取元素。
package chapter_3_StacksandQueues;
/**
* @author LiangGe
* 栈的基本操作
*/
class Stack_3 {
private int size;
private int stack[];
private int top = -1;
public Stack_3(int size) {
this.size = size;
stack = new int[size];
top = -1;
}
public boolean isFull() {
return top == (size-1);
}
public boolean isEmpty() {
return top == -1;
}
public void push(int data) {
if(isFull()) {
//System.out.println("Stack is full!");
return;
}
stack[++top] = data;
}
public void pop() {
if(isEmpty()) {
//System.out.println("Stack is empty!");
return;
}
top --;
}
public int top() {
if(isEmpty()) {
//System.out.println("Stack is empty!");
return -1;
}
return stack[top--];
}
}
/**
* @author LiangGe
* 大栈操作
*/
class SetOfStacks{
private int childStack;
private Stack_3 stack[];
private int curStack;
public SetOfStacks(int size) {
childStack = size;
stack = new Stack_3[childStack];
for(int i=0; i<childStack; i++) {
stack[i] = new Stack_3(childStack);
}
curStack = 0;
}
/**
* 是否栈满
* 栈满条件为子栈为最大且同时也满栈
* @return
*/
public boolean isFull() {
return curStack == (childStack-1) && stack[curStack].isFull();
}
/**
* 是否栈空
* 栈空条件为子栈是否最小且同时为空
* @return
*/
public boolean isEmpty() {
return curStack == 0 && stack[curStack].isEmpty();
}
public void push(int data) {
if(isFull()) {
System.out.println("Stack is full!");
return;
}
if(stack[curStack].isFull()) {
curStack ++;
}
stack[curStack].push(data);
}
public void pop() {
if(isEmpty()) {
System.out.println("Stack is empty!");
return;
}
if(stack[curStack].isEmpty()) {
curStack --;
}
stack[curStack].pop();
}
public int top() {
if(isEmpty()) {
System.out.println("Stack is empty!");
return -1;
}
if(stack[curStack].isEmpty()) {
curStack --;
}
return stack[curStack].top();
}
}
/**
* @author LiangGe
*
* 栈就像叠盘子,当盘子叠得太高时,就会倾斜倒下。因此,在真实的世界中,当一叠盘子 (栈)超过了一定的高度时,我们就会另起一堆,再从头叠起。
* 实现数据结构SetOfStacks 来模拟这种情况。SetOfStacks由几个栈组成,当前一栈超出容量时,需要创建一个新的栈 来存放数据。
* SetOfStacks.push()和SetOfStacks.pop()的行为应当和只有一个栈时 表现的一样。
*
*/
public class Question_3_3 {
public static void main(String args[]) {
SetOfStacks setOfSatacks = new SetOfStacks(3);
for(int i=0; i<10; i++) {
setOfSatacks.push(i);
}
for(int i=0; i< 11 ;i++) {
int top = setOfSatacks.top();
if(top != -1) {
System.out.println("Top stack :" + top);
}
}
}
}
如果考虑进一步的操作popAt(int index)时,
public int top() {
if(isEmpty()) {
System.out.println("Stack is empty!");
return -1;
}
while(stack[curStack].isEmpty()) {
curStack --;
}
return stack[curStack].top();
}
public void pop() {
if(isEmpty()) {
System.out.println("Stack is empty!");
return;
}
while(stack[curStack].isEmpty()) {
curStack --;
}
stack[curStack].pop();
}
public void popAt(int index) {
stack[index].pop();
}
则如果考虑中间栈元素需要出栈,则会使得中间元素栈内有空闲位置,此时如果考虑牺牲空间问题,则空闲位置继续空闲。
则此时在上述问题中只需要考虑出栈操作,因为入栈操作没有变化,只是出栈操作需要判断。
如果元素出栈,则首先判断大栈是否为空,如果不为空则出栈,此时出栈首先判断当前子栈是否为空,为空则需要while循环往前查找
下一个非空子栈。
while(stack[curStack].isEmpty()) {
curStack --;
}
所需只需要在出栈和获取栈顶元素代码出进行修改即可
public int top() {
if(isEmpty()) {
System.out.println("Stack is empty!");
return -1;
}
while(stack[curStack].isEmpty()) {
curStack --;
}
return stack[curStack].top();
}
public void pop() {
if(isEmpty()) {
System.out.println("Stack is empty!");
return;
}
while(stack[curStack].isEmpty()) {
curStack --;
}
stack[curStack].pop();
}
public void popAt(int index) {
stack[index].pop();
}