Cracking the coding interview--Q3.1

原文:

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值