原文:
Describe how you could use a single array to implement three stacks.
译文:
你如何只用一个数组实现三个栈?
如果实现使用一个数组表示一个栈就简单很多,一个指针指向当前栈顶元素位置,初始top=-1,表示栈为空
如果入栈则top++,并元素入栈即可,出栈也只需要top--,top指向栈顶元素。
方法一:
如果用一个数组代表三个栈的操作,假设前天不知道每个栈所需要的空间大小,则可以使用数组等分,每个栈使用
三分之一空间,各个栈都有自己的栈顶指针来操作自己的空间。
package chapter_3_StacksandQueues;
class Stack_1 {
private int stack[];
private int size;
// 分别记录三个栈顶指针位置,栈顶指针指向当前栈最高元素
private int top[] = new int[3];
private int bottom[] = new int[3];
public Stack_1(int size) {
stack = new int[size * 3];
this.size = size;
top[0] = bottom[0] = -1;
top[1] = bottom[1] = size * 1 -1;
top[2] = bottom[2] = size * 2 -1;
}
public boolean isEmpty(int stackNum) {
return top[stackNum] == (stackNum * size -1);
}
public boolean isFull(int stackNum) {
return top[stackNum] == ((stackNum+1) *size - 1);
}
public void push(int stackNum, int value) {
if(isFull(stackNum)) {
System.out.println("Stack num :" + stackNum + " is full!");
return;
}
stack[++ top[stackNum]] = value;
}
public int top(int stackNum) {
if(isEmpty(stackNum)) {
System.out.println("Stack num :" + stackNum + " is empty!");
return -1;
}
return stack[top[stackNum]];
}
public void pop(int stackNum) {
if(isEmpty(stackNum)) {
System.out.println("Stack num :" + stackNum + " is empty!");
return;
}
top[stackNum]--;
}
// 清空并输出
public String getSatckandClear(int stackNum) {
StringBuilder result = new StringBuilder();
// 当前不空
while(!isEmpty(stackNum)) {
result.append(" " + top(stackNum));
pop(stackNum);
}
return result.toString();
}
}
/**
*
* 你如何只用一个数组实现三个栈?
*
*/
public class Question_3_1 {
public static void main(String args[]) {
Stack_1 stack = new Stack_1(5);
int stackNum = 0;
System.out.println("stackNum " + stackNum + " is Empty :" + stack.isEmpty(stackNum));
for(int i=0; i<3; i++) {
for(int j=i*10, k=1; k<=10; k++,j++) {
stack.push(i, j);
}
}
for(int i=0; i<3; i++) {
String result = stack.getSatckandClear(i);
System.out.format("stack %d : %s\n", i, result);
}
}
}
方法二:
如果考虑三个栈直接使用同一个数组,这个可以灵活各个栈空间大小,不约束于三分之一。这样连续使用则每个栈都有自己的栈顶指针
但是同时由于站内数据混在一起,则需要每个栈当前栈顶元素,如果出栈,则需要找到其前一个元素,此时需要记录每个元素的前继元
素在数组中的下标,所以数组元素就不能单纯使用基本类型了,可以使用c++的结构体,java中则使用类
class Node {
public int data;
public int pre;
}
此时对于操作流程中则需要注意每个栈的出栈和入栈,如果只是单纯各管自己的,每次出栈去数组最高位,则考虑如果栈1一直出栈,最终为空
而此时栈2入栈则单纯只考虑数组最高位则浪费了栈1出栈的位置空间,所以每次都需要有一个全部栈空间指针stack_top,随时指针当前最低位空闲位置
每次有元素需要出栈的时候,元素出栈,如果元素位置比全部stack_top要低位,则更新stack_top为当前出栈位置,如果要高则无需变动,这样实时保证
下次入栈时候能利用最低位空闲位置。
每次有元素需要入栈,则stack_top记录最低位入栈,但是stack_top的下一个高位比一定是空闲位置,所以需要往高位扫描直到找到下一个空闲位置,此时
也是整个数组最低位空闲位置。
package chapter_3_StacksandQueues;
class Node {
public int data;
public int pre;
}
class Stack_1_2 {
private Node[] stack;
// 整个栈的大小
private int size;
private int top[] = new int[3];
// 记录当前全局栈顶可存放位置
private int stack_top;
public Stack_1_2(int size) {
stack = new Node[size];
this.size = size;
top[0] = top[1] = top[2] = -1;
stack_top = 0;
for(int i=0; i<size; i++) {
stack[i] = new Node();
stack[i].pre = -2;
}
}
public boolean isEmpty(int stackNum) {
return top[stackNum] == -1;
}
public boolean isFull() {
return stack_top == (size -1);
}
// 入栈
public void push(int stackNum, int data) {
if(isFull()) {
System.out.println("Stack :" + " is full!");
return;
}
int pre = top[stackNum];
stack[stack_top].pre = pre;
stack[stack_top].data = data;
top[stackNum] = stack_top;
// 寻找下一个空闲栈位置
for(int i=stack_top;i<size; i++) {
if(stack[i].pre == -2) {
stack_top = i;
break;
}
}
// 如果没有空闲栈位置,则指向栈顶下一个位置
}
public int top(int stackNum) {
if(isEmpty(stackNum)) {
System.out.println("Stack num :" + stackNum + " is empty!");
return -1;
}
return stack[top[stackNum]].data;
}
// 出栈
public void pop(int stackNum) {
if(isEmpty(stackNum)) {
System.out.println("Stack num :" + stackNum + " is empty!");
return;
}
int now = top[stackNum];
Node node = stack[now];
if(now < stack_top) {
stack_top = now;
}
int pre = node.pre;
top[stackNum] = pre;
node.pre = -2; // 标记为空闲位置
}
public String getSatckData(int stackNum) {
StringBuilder result = new StringBuilder();
int cur = top[stackNum];
while(cur != -1) {
result.append(" " + stack[cur].data);
cur = stack[cur].pre;
}
return result.toString();
}
}
/**
*
* 你如何只用一个数组实现三个栈?
*
*/
public class Question_3_1_2 {
public static void main(String args[]) {
Stack_1_2 stack = new Stack_1_2(20);
int stackNum = 0;
System.out.println("stackNum " + stackNum + " is Empty :" + stack.isEmpty(stackNum));
int stackStart[] = {0, 100, 1000};
// 3 * 3
for(int i=0; i<3; i++) {
for(int k=1; k<=3; k++) {
stack.push(i, stackStart[i] ++);
}
}
// 3 * 3
for(int i=2; i>=0; i--) {
for(int k=1; k<=3; k++) {
stack.push(i, stackStart[i] ++);
}
}
// 3 * 1
for(int i=0; i<3; i++) {
for(int k=1; k<=1; k++) {
stack.push(i, stackStart[i] ++);
}
}
// 输出各个栈的内容
for(int i=0; i<3; i++) {
String result = stack.getSatckData(i);
System.out.format("stack %d : %s\n", i, result);
}
// 栈1出栈5个元素
for(int i=0; i<5;i++) {
System.out.format("stack 0 出栈 top pop : %d\n", i, stack.top(0));
stack.pop(0);
}
// 栈2、3入栈元素
for(int i=1; i<3; i++) {
for(int k=1; k<=3; k++) {
stack.push(i, stackStart[i] ++);
}
}
// 输出各个栈的内容
for(int i=0; i<3; i++) {
String result = stack.getSatckData(i);
System.out.format("stack %d : %s\n", i, result);
}
}
}
参考自:http://hawstein.com/posts/3.1.html