摘自《程序员面试金典》
我们首先最容易想到的就是固定分割的方法:将数组等分为3分,每一份均可以被看做一个栈,然后可以在每个栈上执行出入栈的操作。
这种方法优点是比较直接,实现简单。当然缺点是不够灵活,有可能一个栈出现了空间溢出的情况,而其他栈还是空的状态。
下面说下实现的思路,首先对于长度为n的数组,我们的划分标准如下(假设数组下标从0开始):
1)栈1,使用[0, n/3)
1)栈2,使用[n/3, 2n/3)
1)栈3,使用[2n/3, n)
为了控制每个栈在数组中的活动范围,我们设置常量stackSize表示每个栈的大小,并设置3个常数(stackPointer,使用stackTop命名是不合适的)来记录栈顶的位置,
假设n = 300的话,那么stackSize = 100,而每个stackPointer元素的取值范围为-1 ~ 99(其中-1表示栈为空,0~99表示栈的有效区间)。由于进行
出栈入栈的操作是在一个数组上,所以我们必须能够得到不同的栈的栈顶在数组中位置。假设我们以stackNum(stackNum = 0,1,2)表示将对哪个栈
进行操作,则第stackNum个栈的栈顶位置应该为stackSize * stackNum + stackPointer[stackNum]。由于需要经常使用这个操作,我们将它放到一个独立
的方法topOfStack中去。代码中buffer表示数组。
int stackSize = 100; int[] stackPointer = {-1, -1, -1};
int[] buffer = new int[stackSize * 3];
/*返回栈“stackNum"栈顶元素,在数组中的索引*/ int topOfStack(int stackNum){ return stackSize * stackNum + stackPointer[stackNum]; }
接下来是对栈的操作,我们这里提供出入栈,取栈顶元素的实现(这里假设数组为整数数组)。
1)入栈操作,输入为入栈的元素和带操作的栈序号
void push(int stackNum, int value){ if(stackPointer[stackNum] + 1 >= stackSize) return; //栈顶指针自增,然后更新栈顶元素 stackPointer[stackNum]++; buffer[topOfStack(stackNum)] = value; }
2)出栈操作
int pop(int stackNum) throws Exception{ if(stackPointer[stackNum] == -1) throw new Exception("栈为空,无法出栈"); //获取栈顶的元素,并将栈顶位置清零,同时指针自减 int value = buffer[topOfStack(stackNum)]; buffer[topOfStack(stackNum)] = 0; stackPointer[stackNum] --; return value; }
3)获得栈顶元素
int top(int stackNum) throws Exception{ if(stackPointer[stackNum] == -1) throw new Exception("栈为空,无法获得栈顶元素"); return buffer[topOfStack(stackNum)]; }
完整代码如下所示:
public class StackByArray { int stackSize = 100; int[] stackPointer = {-1, -1, -1}; int[] buffer = new int[stackSize * 3]; void push(int stackNum, int value){ if(stackPointer[stackNum] + 1 >= stackSize) return; //栈顶指针自增,然后更新栈顶元素 stackPointer[stackNum]++; buffer[topOfStack(stackNum)] = value; } int pop(int stackNum) throws Exception{ if(stackPointer[stackNum] == -1) throw new Exception("栈为空,无法出栈"); //获取栈顶的元素,并将栈顶位置清零,同时指针自减 int value = buffer[topOfStack(stackNum)]; buffer[topOfStack(stackNum)] = 0; stackPointer[stackNum] --; return value; } int top(int stackNum) throws Exception{ if(stackPointer[stackNum] == -1) throw new Exception("栈为空,无法获得栈顶元素"); return buffer[topOfStack(stackNum)]; } /*返回栈“stackNum"栈顶元素,在数组中的索引*/ int topOfStack(int stackNum){ return stackSize * stackNum + stackPointer[stackNum]; } public static void main(String[] args) { StackByArray stack = new StackByArray(); stack.push(0, 1); stack.push(0, 2); stack.push(1, 3); stack.push(1, 4); stack.push(2, 11); try { System.out.println(stack.top(2)); stack.pop(2); stack.top(2); } catch (Exception e) { e.printStackTrace(); } } }