copyright:CC150
3.3 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 UPImplement a function popAt(int index) which performs a pop operation on a specific sub-stack.
1.SetOfStacks1->通过定长数组实现子堆栈,popAt(int num)删除某个子堆栈的栈顶元素后,该子堆栈(并非最后一个栈)会通过操作,重新保持最大容量状态,popAt2(int num),删除该子栈顶(并非最后一个栈),该堆栈会保持当前的元素数目,不会维持最大容量状态。
2.SetOfStacks2->通过Node节点来实现子堆栈。popAt(int num)与popAt2(int num)实现原理同上。
import java.util.ArrayList;
import java.util.Scanner;
class SetOfStacks1{
private ArrayList<int[]> list = new ArrayList<int[]>();
private final int MAX_STACK_SIZE = 2;
private int top = -1;
public void push(int val){
if(MAX_STACK_SIZE != 0){//no sense
if(list.size() == 0 || top == MAX_STACK_SIZE -1){
//when perform popAt2(),use stack num [MAX_STACK_SIZE] store top stack num's value
list.add(new int[MAX_STACK_SIZE+1]);
top = -1;
}
int[] s = list.get(list.size()-1);
s[++top] = val;
//used for perform popAt2()
if(top == MAX_STACK_SIZE-1)
s[MAX_STACK_SIZE] = top;
}else{
System.out.println("every substack holds max is zero");
}
}
public int pop(){
if(list.size() == 0 || top == -1){//top == -1 never access
return Integer.MIN_VALUE;
}
System.out.print("<"+(list.size())+">");//display stack number
int[] s = list.get(list.size()-1);
int val = s[top];
top--;
if(top == -1){
list.remove(list.size()-1);
top = MAX_STACK_SIZE - 1;
}
return val;
}
public int pop2(){
if(list.size() == 0 || top == -1){//top == -1 never access
return Integer.MIN_VALUE;
}
System.out.print("<"+(list.size())+">");//display stack number
int[] s = list.get(list.size()-1);
int val = s[top];
top--;
if(top == -1){
list.remove(list.size()-1);
if(list.size() != 0){
s = list.get(list.size()-1);
top = s[MAX_STACK_SIZE];
}
//if wo wanna tp perform : top = s[MAX_STACK_SIZE-1]
}
return val;
}
//after popAt(i), stack i still keep filled, except for the last
//maybe this idea is make better sense
public int popAt(int num){
if(num <= 0 || num > list.size())
return Integer.MIN_VALUE;
//stack's serial number from 1 start
int val = 0;
int[] s = list.get(num-1);
if(list.size() > num){
val = s[MAX_STACK_SIZE-1];
int[] next = null;
int loop = 0;
while(++num <= list.size()){
next = list.get(num-1);
s[MAX_STACK_SIZE-1] = next[0];
if(num == list.size())
loop = top+1;
else
loop = next.length-1;//next[MAX_STACK_SIZE] store the value of top
for(int i=0;i < loop-1;i++)
next[i] = next[i+1];
s = next;
}
}else if(list.size() == num){
val = s[top];
}
top--;
if(top == -1){
list.remove(list.size()-1);
if(!empty())
top = MAX_STACK_SIZE-1;
}
return val;
}
//After substack n execute popAt(), substack n couldn't keep filled
//and if substack is pop to empties, it will be removed
public int popAt2(int num){
//for every substack, use extra space keep track of top
if(num <= 0 || num > list.size())
return Integer.MIN_VALUE;
int[] s = list.get(num-1);
if(num < list.size()){
s[MAX_STACK_SIZE]--;
if(s[MAX_STACK_SIZE] == -1)
list.remove(num-1);
return s[s[MAX_STACK_SIZE]+1];
}else{
return pop();
}
}
public boolean empty(){
if(list.size() == 0)
return true;
else
return false;
}
}
class SetOfStacks2{
private int holds = 0;//record the number of elements that the last Stack has held
private final int CAPACITY = 5;
private ArrayList<Node> list = new ArrayList<Node>();
class Node{
int val;
Node next;
public Node(int val){
this.val = val;
this.next = next;
}
}
public void push(int val){
if(CAPACITY > 0 && holds <= CAPACITY){
//case:holds->the number of sub stacks is zero
//case:holds == CAPACITY->the last substack is filled
if(holds == 0 || holds == CAPACITY){
list.add(new Node(val));
holds = 0;
}else{
Node top = list.remove(list.size()-1);
Node n = new Node(val);
n.next = top;
top = n;
list.add(top);
}
holds++;
}
}
public int pop(){
if(list.size() != 0){
System.out.print("["+list.size()+"]");//
Node top = list.remove(list.size()-1);
Node n = top;
/*
for(Node p = top;p!=null;p=p.next)
System.out.print("["+p.val+"]");
*/
top = top.next;
holds--;
if(holds != 0 && top != null){//enhance condition
list.add(top);
// System.out.println("top.val="+top.val);//
}
return n.val;
}else{
System.out.println("stack is empty!");
return Integer.MIN_VALUE;
}
}
public int pop2(){
if(list.size() != 0){
System.out.print("["+list.size()+"]");//
Node top = list.remove(list.size()-1);
Node n = top;
/*
for(Node p = top;p!=null;p=p.next)
System.out.print("["+p.val+"]");
*/
top = top.next;
holds--;
if(holds != 0 && top != null){//enhance condition
list.add(top);
// System.out.println("top.val="+top.val);//
}else{
if(list.size() != 0){
top = list.get(list.size()-1);
int counter = 0;
for(Node p = top;p != null;p = p.next)
counter++;
holds = counter;
}else{
holds = 0;
}
}
return n.val;
}else{
System.out.println("stack is empty!");
return Integer.MIN_VALUE;
}
}
//After substack n execute popAt(), substack n still keep filled
public int popAt(int num){
//num started from 1
if(num <= 0 || num > list.size()){
System.out.println("substack isn't existed !");
return Integer.MIN_VALUE;
}else{
if(num < list.size()){
Node top = list.get(num-1);
int val = top.val;
Node n = null;
top = top.next;
//num->1 corresponding list.get(0)
for(;num < list.size();){
n = list.get(num);
//the only element n of every sub stack is we wanted to fill the loss
if(n.next == null){
n.next = top;
top = n;
list.set(num-1, top);
list.set(num, null);//n.next == null
//the only element of last sub stack
if(num == list.size()-1){
list.remove(num);
holds = CAPACITY;
break;
}
}else{
for(;n.next.next != null;n = n.next)
;
n.next.next = top;
top = n.next;
n.next = null;
list.set(num-1, top);
if(num == list.size()-1){
holds--;
}
}
//virables increasement
top = list.get(num);
num++;
}
return val;
}else{
return pop();
}
}
}
//After substack n execute popAt(), substack n couldn't keep filled
//and if substack is pop to empties, it will be removed
public int popAt2(int num){
if(num <= 0 || num > list.size()){
System.out.println("substack isn't existed !");
return Integer.MIN_VALUE;
}else{
//the only question is :holds has changed, must be to
//keep synchronization with holds,that would influence
//the performance of pop()
Node top = list.get(num-1);
int val = top.val;
top = top.next;
if(top == null)
list.remove(num-1);
else
list.set(num-1, top);
return val;
}
}
public boolean empty(){
if(list.size() == 0)
return true;
else
return false;
}
}
public class Solution{
public static void main(String[] args){
/*
//test for SetOfStack1.popAt(int num)
SetOfStacks1 sos1 = new SetOfStacks1();
for(int i=1;i <= 20;i++)
sos1.push(i);
System.out.println("sos1.popAt(2)="+sos1.popAt(2));//
for(;!sos1.empty();)
System.out.print(sos1.pop()+" ");
System.out.println();
*/
/*
//test for SetOfStack1.popAt2(int num)
SetOfStacks1 sos1 = new SetOfStacks1();
for(int i=1;i <= 20;i++)
sos1.push(i);
System.out.println("sos1.popAt2(2)="+sos1.popAt2(2));//
for(;!sos1.empty();)
System.out.print(sos1.pop2()+" ");
System.out.println();
*/
/*
//test for SetOfStack2.popAt(int num)
SetOfStacks2 sos2 = new SetOfStacks2();
for(int i=1;i <= 20;i++)
sos2.push(i);
System.out.println("sos2.popAt(2)="+sos2.popAt(2));//
for(;!sos2.empty();)
System.out.print(sos2.pop()+" ");
System.out.println();
*/
//test for SetOfStack2.popAt2(int num)
SetOfStacks2 sos2 = new SetOfStacks2();
for(int i=1;i <= 20;i++)
sos2.push(i);
System.out.println("sos2.popAt(2)="+sos2.popAt2(2));//
System.out.println("sos2.popAt(2)="+sos2.popAt2(2));//
System.out.println("sos2.popAt(2)="+sos2.popAt2(2));//
System.out.println("sos2.popAt(2)="+sos2.popAt2(2));//
for(;!sos2.empty();)
System.out.print(sos2.pop2()+" ");
System.out.println();
}
}