用兩個棧實現隊列(C++ 和 Python 實現)


(說明:本博客中的題目題目詳細說明參考代碼均摘自 “何海濤《劍指Offer:名企面試官精講典型編程題》2012年”)

題目

  用兩個棧實現一個隊列。隊列的聲明如下,請實現它的兩個函數 appendTail 和 deleteHead,分別完成在隊列尾部插入結點和在隊列頭部刪除結點功能。

template <typename T> class CQueue { public: CQueue(void); ~CQueue(void); void appendTail(const T& node); T deleteHead(); };

進一步詳細說明:

  在上述隊列的聲明中可以看出,一個隊列包含兩個棧 stack1 和 stack2,因此這道題的意圖是要求我們操作這兩個 “先進后出” 的棧實現一個 “先進先出” 的隊列 CQueue。

 

算法設計思想

  因為棧是后進先出的數據結構,當將數據依次壓入第一個棧后,再依次從這個棧彈出,壓入第二個棧,如果此時從第二個棧中獲取數據,表現正好像一個 “先進先出” 的隊列數據結構。

  具體來說,使用兩個棧實現一個隊列,可以考慮用第一個棧(stack1)存放輸入的元素(隊尾元素),從第二個棧(stack2)獲取隊頭元素。當第一棧(stack1)為空時,將第二個棧(stack2)中的全部元素依次彈出,再依次壓入第一個棧中。其過程如圖 2.8 所示,

 

C++ 實現

#include <iostream> #include <stack> #include <exception> template <typename T> class CQueue { public: CQueue(void); ~CQueue(void); void appendTail(const T& node); T deleteHead(); private: std::stack<T> stack1; std::stack<T> stack2; }; // Declare queue empty exception when try to pop when the queue is empty.
class QEmptyException: public std::exception { virtual const char* what() const throw() { return "Error: Queue is empty!"; } } popException; // stack1 as input stack, stack2 as output stack
template <typename T>
void CQueue<T>::appendTail(const T& node) { stack1.push(node); } template <class T> T CQueue<T>::deleteHead() { // Check if there are elements in stack2
    if (stack2.empty()) { // Pop all the elements from stack1, then push them onto stack2
        if (stack1.size() > 0) { while (!stack1.empty()) { T elem = stack1.top(); stack1.pop(); stack2.push(elem); } } else
            throw popException; } // Get the top element from stack2, then delete it from stack2
    T elem = stack2.top(); stack2.pop(); return elem; } template <typename T> CQueue<T>::CQueue(void) { } template <typename T> CQueue<T>::~CQueue(void) { } void unitest() { CQueue<int> que; std::cout << "Push 1, 2, 3 successively into CQueue." << std::endl; que.appendTail(1); que.appendTail(2); que.appendTail(3); std::cout << "Pop the head of the queue: " << que.deleteHead() << std::endl; std::cout << "Pop the head of the queue: " << que.deleteHead() << std::endl; std::cout << "Push 4, 5, 6 successively into CQueue." << std::endl; que.appendTail(4); que.appendTail(5); que.appendTail(6); // Pop the rest elements in the queue, until the queue empty exception happens
    for (int i = 0; i < 4; ++i) { std::cout << "Pop the head of the queue: " << que.deleteHead() << std::endl; } } int main() { unitest(); return 0; }

 

Python 實現

#!/usr/bin/python # -*- coding: utf8 -*-

class CQueue: def __init__(self): self.stack1 = [] self.stack2 = [] def append_tail(self, elem): self.stack1.append(elem) def delete_head(self): if not self.stack2: if self.stack1: while self.stack1: elem = self.stack1.pop() self.stack2.append(elem) else: raise Exception("Queue is empty.") elem = self.stack2.pop() return elem def unitest(): # Create an instance of class CQueue
    que = CQueue() print "Push 1, 2, 3 successively into CQueue."
    for i in range(1, 4): que.append_tail(i) print "Pop the head of the queue:", que.delete_head() print "Pop the head of the queue:", que.delete_head() print "Push 4, 5, 6 successively into CQueue."
    for i in range(4, 7): que.append_tail(i) # Pop the rest elements in the queue
    for i in range(4): print "Pop the head of the queue:", que.delete_head() if __name__ == '__main__': unitest()

 

參考代碼

1. targetver.h

#pragma once

// The following macros define the minimum required platform. The minimum required platform // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run // your application. The macros work by enabling all features available on platform versions up to and // including the version specified. // Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
#endif
View Code

2. stdafx.h

// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // 
#pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h>



// TODO: reference additional headers your program requires here
View Code

3. stdafx.cpp

// stdafx.cpp : source file that includes just the standard includes // QueueWithTwoStacks.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information
 #include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H // and not in this file
View Code

4. Queue.h

#pragma once #include <stack> #include <exception>

using namespace std; template <typename T> class CQueue { public: CQueue(void); ~CQueue(void); // 在隊列末尾添加一個結點
    void appendTail(const T& node); // 刪除隊列的頭結點
 T deleteHead(); private: stack<T> stack1; stack<T> stack2; }; template <typename T> CQueue<T>::CQueue(void) { } template <typename T> CQueue<T>::~CQueue(void) { } template<typename T> void CQueue<T>::appendTail(const T& element) { stack1.push(element); } template<typename T> T CQueue<T>::deleteHead() { if(stack2.size()<= 0) { while(stack1.size()>0) { T& data = stack1.top(); stack1.pop(); stack2.push(data); } } if(stack2.size() == 0) throw new exception("queue is empty"); T head = stack2.top(); stack2.pop(); return head; }
View Code

5. Queue.cpp

#include "StdAfx.h" #include "Queue.h" #include <queue>
View Code

6. QueueWithTwoStacks.cpp

// QueueWithTwoStacks.cpp : Defines the entry point for the console application. //

// 《劍指Offer——名企面試官精講典型編程題》代碼 // 著作權所有者:何海濤
 #include "stdafx.h" #include "Queue.h"

void Test(char actual, char expected) { if(actual == expected) printf("Test passed.\n"); else printf("Test failed.\n"); } int _tmain(int argc, _TCHAR* argv[]) { CQueue<char> queue; queue.appendTail('a'); queue.appendTail('b'); queue.appendTail('c'); char head = queue.deleteHead(); Test(head, 'a'); head = queue.deleteHead(); Test(head, 'b'); queue.appendTail('d'); head = queue.deleteHead(); Test(head, 'c'); queue.appendTail('e'); head = queue.deleteHead(); Test(head, 'd'); head = queue.deleteHead(); Test(head, 'e'); return 0; }
View Code

7. 參考代碼下載

項目 07_QueueWithTwoStacks 下載: 百度網盤

何海濤《劍指Offer:名企面試官精講典型編程題》 所有參考代碼下載:百度網盤

 

參考資料

[1]  何海濤. 劍指 Offer:名企面試官精講典型編程題 [M]. 北京:電子工業出版社,2012. 58-62.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM