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