1. 程式人生 > >使用兩個佇列實現一個棧,使用兩個棧實現一個佇列!

使用兩個佇列實現一個棧,使用兩個棧實現一個佇列!

轉自:http://blog.csdn.net/zgh1988/article/details/6988904

時間:小師妹請客之後,2013/6/16

1、這裡所說的都是STL中的queue,stack

     其中queue的特點是先進先出,它所具有的函式有:

     queue<int>

     void push(int elem)                              //向佇列中新增元素

     void pop()                                              //從佇列中刪除頭元素,即先進入的先出去

     int front();                                               //返回佇列中的頭元素,即佇列中最先進入的元素

     int back();                                               //返回佇列中的末尾元素,即佇列中的最後進入的元素

      int size() const;                                    //返回佇列中元素的個數

     bool empty() const ;                            // 判斷佇列是否為空,空返回true,非空返回false。

    其中stack 的特點是後進先出,它所具有的函式有:

   stack<int>

    void push(int elem);                             // 向棧中新增一個元素

    void pop();                                              //刪除棧中的一個元素,即最後進入的元素

    int top() const;                                       // 返回棧中的頭元素,即最後進入的元素。

    int size() const;                                     // 返回棧中元素的個數

    bool empty() const;                             // 判斷棧是否為空,空返回true,非空返回false;

2、如何使用兩個佇列實現一個棧

         (1)  使用兩個佇列 q1, q2, 還有兩個bool變數 q1_used, q2_used,分別表示q1是否在使用,q2是否在使用,兩者只有一個在使用,另一個不在使用。初始狀態為 q1_used = true;  q2_used = false;即此時q1在使用,q2閒置。

          (2) 實現棧的push操作,首先判斷q1_used,q2_used,然後找出正在使用佇列,將其新增到佇列中。例如q1_used == true;  則將元素新增到佇列q1;  反之q2_used == true,則將元素新增到佇列q2中。

           (3)  實現棧的pop操作,首先判斷q1_used ,q2_used,找出正在使用的佇列,然後將在使用的佇列元素取出來,放到閒置的佇列中,刪除佇列最後一個元素。然後修改q1_used, q2_used.

              例如初始狀態為q1_used = true,a,b,c入棧,則將其插入佇列q1中,然後執行出棧操作pop,則將a,b從q1中出佇列,然後進入q2,將c進行pop操作。

                       

                  (4)執行top操作,判斷q1_used q2_used,然後找出正在使用的佇列,利用該佇列函式back(),返回棧頭元素值。

                   (5) 至於size()和empty()操作,就對正在使用的佇列,執行size()和empty()函式,返回值。

下面為實現程式碼:

#ifndef STACK_H
#define STACK_H

#include <queue>
#include <iostream>

template <typename T>
class Stack {
private:
 std::queue<T> q1;
 std::queue<T> q2;
 bool q1_used, q2_used;
public:
 Stack();
 void push(T elem);
 void pop();
 T top() const;
 bool empty() const;
 int size() const;
};

template <typename T>
Stack<T>::Stack() {
 q1_used = true;
 q2_used = false;
}

template <typename T>
void Stack<T>::push(T elem) {
 if(q1_used == true) {
  q1.push(elem);
 }
 if(q2_used == true) {
  q2.push(elem);
 }
}

template <typename T>
void Stack<T>::pop() {
 if(!q1.empty() && q1_used == true) {
  while(q1.size() != 1) {
   q2.push(q1.front());
   q1.pop();
  }
  q1.pop();
  q2_used = true;
  q1_used = false;
  return;
 }
 if(!q2.empty() && q2_used == true) {
  while(q2.size() != 1) {
   q1.push(q2.front());
   q2.pop();
  }
  q2.pop();
  q2_used = false;
  q1_used = true;
  return;
 }
 std::cout << "error! Stack::pop()" << std::endl;
}

template <typename T>
T Stack<T>::top() const {
 if(!q1.empty() && q1_used == true) {
  return q1.back();
 }
 else if(!q2.empty() && q2_used == true) {
  return q2.back();
 }
 std::cout << "error! Stack::top()" << std::endl;
 return 0;
}

template <typename T>
bool Stack<T>::empty() const {
 return q1.empty() && q1_used == true || q2.empty() && q2_used == true;
}

template <typename T>
int Stack<T>::size() const {
 if(!q1.empty() && q1_used == true) {
  return q1.size();
 }
 if(!q2.empty() && q2_used == true) {
  return q2.size();
 }
 return 0;
}

#endif

測試程式為:

#include "Stack.h"

int main() {
 Stack<int> s1;
 s1.push(4);
 s1.push(5);
 std::cout << s1.top() << ' ' << s1.size() << std::endl;
 s1.pop();
 std::cout << s1.top() << ' ' << s1.size() << std::endl;
 s1.pop();
 s1.top();
 s1.pop();
 s1.push(6);
 s1.push(7);
 s1.push(8);
 std::cout << s1.top() << ' ' << s1.size() << std::endl;
 s1.pop();
 std::cout << s1.top() << ' ' << s1.size() << std::endl;
}

測試結果

3、使用兩個棧來實現一個佇列

          (1) 使用兩個棧s1,s2,其中假定s1負責push操作, s2負責pop操作。使用一個變數back_elem來儲存最後新增的元素。

          (2)  實現佇列的push操作,  每次進行新增操作,都會相應得對棧s1進行新增元素。並對back_elem賦值

          (3) 實現佇列的pop操作,每次進行刪除操作,因為s2負責pop操作,

首先判斷棧s2是否為空?

如果s2為空,則判斷s1是否為空? 

            如果s1也為空, 則輸出錯誤資訊,此時佇列為空。

            如果s1不為空,  則將棧s1中的所有資料儲存到s2中。執行s2.push(s1.top()),   s1.pop().     然後在對棧s2執行,s2.pop()操作,將佇列的頭元素刪除

如果s2不為空, 則直接對s2執行 s2.pop()操作。

           例如對a,b,c實現push操作,然後實現pop操作

                   

          (4)實現佇列的front()操作,方法如pop操作相同,只是在最後一步使用s2.top()返回值。

          (5)實現佇列的back()操作,因為我們變數back_elem儲存著最後一個輸入的資料,故直接將其返回。

          (6)實現佇列的size()操作,和empty()操作,就是對s1,s2分別執行操作。

  實現程式碼:

#ifndef QUEUE_H
#define QUEUE_H
#include <iostream>
#include <stack>

template<typename T>
class Queue {
private:
 std::stack<T> s1;
 std::stack<T> s2;
 T back_elem;
public:
 void push(T elem);
 void pop();
 T front();
 T back();
 int size() const;
 bool empty() const;
};

template<typename T>
void Queue<T>::push(T elem) {
 s1.push(elem);
 back_elem = elem;
}

template<typename T>
void Queue<T>::pop() {
 if(!s2.empty()) {
  s2.pop();
 }
 else if(!s1.empty()) {
  while(!s1.empty()) {
   s2.push(s1.top());
   s1.pop();
  }
  s2.pop();
 }
 else {
  std::cout << "error pop(), empty queue!" << std::endl;
 }
}

template<typename T>
T Queue<T>::front(){
 if(!s2.empty()) {
  return s2.top();
 }
 else if(!s1.empty()) {
  while(!s1.empty()) {
   s2.push(s1.top());
   s1.pop();
  }
  return s2.top();
 }
 else {
  std::cout << "error front(), empty queue!" << std::endl;
 }
}

template<typename T>
T Queue<T>::back(){
 if(!empty())
  return back_elem;
 else {
  std::cout << "error back(), empty queue!" << std::endl;
  return 0;
 }
}

template<typename T>
int Queue<T>::size() const {
 return s1.size() + s2.size();
}

template<typename T>
bool Queue<T>::empty() const {
 return s1.empty() && s2.empty();
}

#endif

測試程式

#include "Queue.h"
#include <string>

int main() {
 Queue<int> queue;
 queue.push(4);
 queue.push(5);
 queue.push(6);

 std::cout << queue.front() << ' ' << queue.back() << ' ' << queue.size() << std::endl;

 queue.pop();
 queue.pop();
 std::cout << queue.front() << ' ' << queue.back() << ' ' << queue.size() << std::endl;
 queue.pop();
 queue.pop();

 Queue<std::string> queue2;
 queue2.push("Hello");
 queue2.push("World");
 queue2.push("!!!!");

 std::cout << queue2.front() << ' ' << queue2.back() << ' ' << queue2.size() << std::endl;

 queue2.pop();
 queue2.pop();
 std::cout << queue2.front() << ' ' << queue2.back() << ' ' << queue2.size() << std::endl;
 queue2.pop();
 queue2.pop();
 return true;
}

測試結果: