1 实现原理和步骤
假如存在两个以数组为存储的栈1和栈2,其中栈1已满了,而栈2还有空间。如果需要继续往栈1插入数据,则需要栈1重新扩容,即将栈1中数组的数据再复制一遍的另外一个容量更大的栈中,这样存在空间浪费和效率低的问题。
面对这种场景,可以使用两栈共享内存的方式,提高空间利用率。开辟一个数组,从位置0开始依次存放栈1的元素,从末端开始存放栈2的元素,每存放一个元素栈指针移动一位,从而提高了空间利用率。当栈1指针的位置 – 栈2指针的位置= 1,说明数组存储已满。
另外,这种方法也是有缺点,只适合于存储相同类型的两个栈。
2 完整代码
package stack;
/**
* 两栈共享内存
* @param <E>
*/
public class DoubleStack <E>{
/**
* 使用数组实现栈
*/
private Object[] elementData;
/**
* 栈1顶点的位置
*/
private int top1;
/**
* 栈2顶点的位置
*/
private int top2;
/**
* 有参构造函数
* @param size
*/
public DoubleStack(int size){
elementData = new Object[size];
top1 = -1;
top2 = elementData.length;
}
/**
* 插入元素item为新的栈顶元素
* @param stackNum 1表示插入栈1,2表示从插入栈2
* @param item 新元素
* @return
*/
public E push(int stackNum, E item) {
if(top2 - top1 == 1){
throw new RuntimeException("栈已经满了!");
}
if(stackNum == 1){
elementData[++top1] = item;
}else{
elementData[--top2] = item;
}
return item;
}
/**
* 查询顶元素
* @param stackNum 1表示插入栈1,2表示从插入栈2
* @return
*/
public E peek(int stackNum) {
if(stackNum == 1){
if (top1 == -1){
throw new RuntimeException("栈1为空!");
}
return (E)elementData[top1];
}else{
if (top2 == elementData.length){
throw new RuntimeException("栈2为空!");
}
return (E)elementData[top2];
}
}
/**
* 弹出堆顶元素
* @param stackNum 1表示插入栈1,2表示从插入栈2
* @return
*/
public E pop(int stackNum) {
E obj = null;
if(stackNum == 1){
if (top1 == -1){
throw new RuntimeException("栈1为空!");
}
obj = (E)elementData[top1];
top1--;
}else{
if (top2 == elementData.length){
throw new RuntimeException("栈2为空!");
}
obj = (E)elementData[top2];
top2++;
}
return obj;
}
/**
* 查看栈是否为空
* @param stackNum 1表示插入栈1,2表示从插入栈2
* @return
*/
public boolean empty(int stackNum) {
if(stackNum == 1){
return top1 == -1;
}else{
return top2 == elementData.length;
}
}
/**
* 遍历栈
* @param stackNum 1表示插入栈1,2表示从插入栈2
* @return
*/
public String travelsal(int stackNum){
StringBuilder ret = new StringBuilder("{");
if (stackNum == 1){
while (top1 != -1){
ret.append(pop(1) + ", ");
}
}else {
while (top2 != elementData.length){
ret.append(pop(2) + ", ");
}
}
return ret.replace(ret.length() - 2, ret.length(), "}").toString();
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
DoubleStack<String> stack = new DoubleStack<String>(10);
for (int i = 0; i < 5; i++){
stack.push(1, "element_" + i );
stack.push(2, "element_" + (10 - i) );
}
System.out.println("栈1的顶元素:" + stack.peek(1));
System.out.println("栈2的顶元素:" + stack.peek(2));
System.out.println("遍历栈1的元素:" + stack.travelsal(1));
System.out.println("遍历栈2的元素:" + stack.travelsal(2));
}
}
3 测试结果
栈1的顶元素:element_4
栈2的顶元素:element_6
遍历栈1的元素:{element_4, element_3, element_2, element_1, element_0}
遍历栈2的元素:{element_6, element_7, element_8, element_9, element_10}
4 参考文献
[1]程杰. 大话数据结构[M]. 清华大学出版社,2011