劍指Offer面試題7(Java版):用兩個棧實現佇列與用兩個佇列實現棧
題目:用兩個棧實現一個佇列。佇列的宣告如下,請實現它的兩個函式appendTail和deletedHead,分別完成在佇列尾部插入節點和在佇列頭部刪除節點的功能。
我們通過一個具體的例子來分析該佇列插入和刪除元素的過程。首先插入一個元素a,不妨先把它插入到stack1,此時stack1 中的元素有{a},stack2為空。再壓入兩個元素b和c,還是插入到stack1中,此時stack1中的元素有{a,b,c},其中c位於棧頂,而stack2仍然為空。
這個時候,我們試著刪除從佇列中刪除一個元素。按照佇列先入先出的規則,由於a比b、c先插入到佇列中,最先被刪除的元素應該是a。元素a儲存在stack1中,但並不在佔頂上,因此不能直接被刪除。注意到stack2我們還一直沒有使用過,現在是讓stack2發揮作用的時候了。如果我們把stack1中的元素逐個彈出並壓入stack2,元素在stack2中的順序正好和原來的stack1中的順序相反。因此經過3次彈出stack1和壓入stack2操作之後,stack1為空,而stack2中的元素是{c,b,a},這個時候就可以彈出stack2的棧頂a了。此時的stack1為空,而stack2的元素為{c,b},其中在棧頂,如圖所示:
Java程式碼實現:
/** * */ package swordForOffer; import java.util.Stack; /** * @author JInShuangQi * * 2015年7月27日 */ public class E07QueueWithTwoStacks { /** * 用兩個棧實現一個佇列,完成兩個函式appendTail和deletedHead,分別是在佇列尾部插入節點 * 和在佇列頭部刪除節點的功能 */ private Stack<String> stack1 = new Stack<String>(); private Stack<String> stack2 = new Stack<String>(); public void appendTail(String s){ stack1.push(s); } public String deletedHead() throws Exception{ if(stack2.isEmpty()){ while(!stack1.isEmpty()){ stack2.push(stack1.pop()); } } if(stack2.isEmpty()){ throw new Exception("佇列為空,不能刪除"); } return stack2.pop(); } public static void main(String[] args) throws Exception{ E07QueueWithTwoStacks test = new E07QueueWithTwoStacks(); test.appendTail("1"); test.appendTail("2"); test.deletedHead(); } }
用兩個佇列實現棧。
通過一系列的棧的壓入和彈出操作來分析用佇列模擬一個棧的過程,如圖所示,我們先往棧內壓入一個元素a。由於兩個佇列現在都是空,我們可以選擇把a插入兩個佇列中的任一個。我們不妨把a插入queue1。接下來繼續網棧內壓入b,c兩個元素。我們把它們都插入queue1。這個時候 queue1包含3個元素a,b,c其中a位於佇列的頭部,c位於佇列的尾部。
現在我們考慮從棧內彈出一個元素。根據棧的後入先出的原則,最後被壓入棧的c應該最先被彈出。由於c位於queue1的尾部,而我們每次只能從佇列的頭部刪除元素,因此我們可以從queueu中依次刪除a/b/c並插入到queue2中,再從queue1中刪除c。這就相當於從棧中彈出元素c了。我們可以用同樣的方法從棧內彈出元素b。
接下來我們考慮從棧內壓入一個元素d.此時queue1已經有了一個元素,我們就把d插入到queue1的尾部。如果我們再從棧內彈出一個元素,此時被彈出的應該是最後被壓入的d.由於d位於queue1的尾部,我們只能先從頭部刪除 queue1的元素並插入到queue2,直到queue1中遇到d再直接把它刪除。如圖所示:
Java程式碼實現:
/**
*
*/
package swordForOffer;
import java.util.LinkedList;
/**
* @author JInShuangQi
*
* 2015年7月27日
*/
public class E07StacksWithTwoQueue {
private LinkedList<String> queue1;
private LinkedList<String> queue2;
public E07StacksWithTwoQueue(){
queue1 = new LinkedList<String>();
queue2 = new LinkedList<String>();
}
public String pop(){
String re =null;
if(queue1.size() == 0 && queue2.size() == 0){
return null;
}
if(queue2.size() == 0){
while(queue1.size() >0){
re = queue1.removeFirst();
if(queue1.size() != 0){
queue2.addLast(re);
}
}
}else if(queue1.size() == 0){
while(queue2.size() >0){
re = queue2.removeFirst();
if(queue2.size()!=0){
queue1.addLast(re);
}
}
}
return re;
}
public String push(String str){
if(queue1.size() ==0 && queue2.size() == 0){
queue1.addLast(str);
}else if(queue1.size()!=0){
queue1.addLast(str);
}else if(queue2.size()!=0){
queue2.addLast(str);
}
return str;
}
public static void main(String[] args) {
E07StacksWithTwoQueue stack=new E07StacksWithTwoQueue();
String tmp;
stack.push("1");
stack.push("2");
stack.push("3");
tmp=stack.pop();
System.out.println(tmp);//3
stack.push("4");
tmp=stack.pop();
System.out.println(tmp);//4
tmp=stack.pop();
System.out.println(tmp);//2
stack.push("5");
stack.push("6");
tmp=stack.pop();
System.out.println(tmp);//6
tmp=stack.pop();
System.out.println(tmp);//5
tmp=stack.pop();
System.out.println(tmp);//1
}
}