棧和隊列面試題(一):棧和隊列的相互實現

關於棧和隊列的考察

  棧和隊列都是比較經常使用的數據結構。棧的應用很是的普遍,好比說,遞歸函數的實現就是藉助於棧保存相關的數據。操做系統中每一個線程也會使用棧來保存函數調用涉及到的一些參數和其餘變量等。棧最大的一個特色就是先進後出(FILO—First-In/Last-Out)。
  隊列和棧不一樣的是,隊列是一種先進先出(FIFO—first in first out)的數據結構。node

  對應的STL中都有實現了的方法。面試

  棧的相關方法:數據結構

入棧,s.push(x)
出棧,s.pop()
訪問棧頂,s.top()
判斷棧空,s.empty()
訪問棧中的元素個數,s.size()

 

 

 

 

隊列的方法與棧大同小異,列舉以下:app

入隊,q.push(x)
出隊,q.pop()
訪問隊首元素,q.front()、訪問隊尾元素,q.back()
判斷隊列空,q.empty()
訪問隊列中的元素個數,q.size()

 

 

 

 

注意,二者的pop()方法,僅僅刪除棧頂和隊列首元素,並不返回,如需截獲元素,在pop()方法以前使用top()或者front()方法。函數

面試題1:

用兩個棧實現隊列,請實現兩個函數appendTail和deleteHead,完成在隊列尾部插入結點和在隊列首部刪除結點的功能。模板定義以下:spa

 

 1 template <typename T> class CQueue
 2 {
 3 public:
 4     CQueue(void);
 5     ~CQueue(void);
 6     
 7     // 在隊列末尾添加一個結點
 8     void appendTail(const T& node);
 9 
10     // 刪除隊列的頭結點
11     T deleteHead();
12 
13 private:
14     stack<T> stack1;
15     stack<T> stack2;
16 };

 分析:操作系統

  這道題是要求經過兩個「先進後出」的操做完成「先進先出」的功能。下面這個例子比較形象的給出了實現的過程。線程

  起初的時候,兩個棧都爲空,那麼只要有元素來,那麼默認插入到第一個棧。這是,若是要求刪除一個元素,那麼元素已經不在棧頂,在第一個棧中確定沒法直接刪除了,此時咱們發現第二個棧尚未派上用場,這裏用到了,把第一個棧中的元素壓入到第二個棧中,能夠發現原來在第一個棧中棧底的元素已經出如今第二個棧的棧頂上,因此刪除的功能就實現了。若是這個時候,「隊列」裏還有元素,咱們還能夠繼續出隊,並且,如今要出隊的元素就在第二個棧的棧頂,因此直接出棧便可。code

  分析到如今,下面給出總結:若是棧2不爲空,同時又須要出隊,那麼順其天然直接彈出便可。若是棧2爲空,那麼從棧1中逐個彈出壓入,那麼完整的實現了先進先出的功能。blog

  具體的流程和代碼實現以下:

  

 1 template<typename T> void CQueue<T>::appendTail(const T& element)
 2 {
 3     stack1.push(element);
 4 } 
 5 
 6 template<typename T> T CQueue<T>::deleteHead()
 7 {
 8     if(stack2.size()<= 0)
 9     {
10         while(stack1.size()>0)
11         {
12             T& data = stack1.top();
13             stack1.pop();
14             stack2.push(data);
15         }
16     }
17 
18     if(stack2.size() == 0)
19         throw new exception("queue is empty");
20 
21     T head = stack2.top();
22     stack2.pop();
23 
24     return head;
25 }

面試題2:

用兩個隊列實現棧。

分析:

  結合下圖,咱們分析一下具體的流程,搞清楚了相關的流程,那麼對應的操做就明晰了。

  起初的時候,兩個隊列都是空的,那麼當「棧」要壓入一個元素,咱們就默認將該元素壓入到隊列1中。接下來繼續壓入剩餘的元素。

  接下來考慮,若是咱們想要彈出一個元素如何操做。棧中要求出棧的爲棧頂元素,那麼即爲最後插入的元素,可是該元素在隊列的尾部,必需要求前面的元素出隊後才能訪問,說到這裏,你也就發現思路的:出隊前面的元素,到另外一個隊列中,那麼就能夠在原隊列中彈出惟一的元素了。

  如今咱們再考慮另外一個狀況,隊列裏面還有元素,「棧」又進來了新的元素,那麼就將新元素,壓入到存在元素的那一個隊列中,剩餘的操做,上面已經提到了,同樣的操做,看圖也許就清晰多了。

 1 template <typename T> class CStack
 2  {
 3  public:
 4      CStack(void);
 5      ~CStack(void);
 6      
 7       // 在隊列末尾添加一個結點
 8       void Input(const T& );
 9   
10      // 刪除隊列的頭結點
11      T Output();
12 
13  private:
14      queue<T> queue1;
15      queue<T> queue2;
16  };
 1  template<typename T> void CStack<T>::Input(const T& t){
 2      if(queue1.empty()&&queue2.empty())
 3          queue1.push(t);
 4      else
 5          if(!queue1.empty())
 6             queue1.push(t); 
 7         else
 8             queue2.push(t);
 9  }
10  
11  template<typename T> T CStack<T>::Output(){
12     T t;
13     if(queue1.empty()&&queue2.empty())
14         retutn NULL;
15     else
16         if(queue1.empty()){
17             while(queue2.size()!=1){
18                 queue1.push(queue2.front());
19                 queue2.pop();
20             }
21             t=queue2.front();
22             queue2.pop();
23         }
24         else
25         {
26             while(queue1.size()!=1){
27                 queue2.push(queue1.front());
28                 queue1.pop();
29             }
30             t=queue1.front();
31             queue1.pop();
32         }
33          return t;
34  }
35  
相關文章
相關標籤/搜索