1. 程式人生 > >劍指Offer面試題7(Java版):用兩個棧實現佇列與用兩個佇列實現棧

劍指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  
	 }
}