(1)基本的Stack:以std::deque為內部容器。方法有入棧、出棧、返回棧頂元、判斷棧空。
//stack1.h:棧的基本實現<br />#ifndef __STACK1_H__<br />#define __STACK1_H__<br />#include <deque><br />#include <stdexcept><br />template<typename T><br />class Stack{<br />private:<br />std::deque<T> elems; //包含元素的容器<br />public:<br />void push(T const&); //壓入元素<br />void pop(); //彈出元素<br />T top() const; //返回棧頂元素<br />bool empty() const{ //判斷棧是否為空白<br />return elems.empty();<br />}<br />};<br />template<typename T><br />void Stack<T>::push(T const& elem){<br />elems.push_back(elem); //把元素的拷貝添加到末端<br />}<br />template<typename T><br />void Stack<T>::pop(){<br />if(elems.empty()){<br />throw std::out_of_range("Stack<T>::pop(): empty stack");<br />}<br />elems.pop_back(); //刪除末端元素<br />}<br />template<typename T><br />T Stack<T>::top() const{<br />if(elems.empty()){<br />throw std::out_of_range("Stack<T>::top(): empty stakc");<br />}<br />return elems.back(); //返回末端元素的拷貝<br />}<br />#endif
測試程式:
//stack1test.cpp:測試Stack<br />#include <iostream><br />#include <string><br />#include <cstdlib><br />#include "stack1.h"<br />int main(){<br /> try{<br /> Stack<int> intStack; //元素類型為int的棧<br /> Stack<std::string> stringStack; //元素類型為string的棧<br /> intStack.push(7);<br /> std::cout<<intStack.top()<<std::endl;<br /> stringStack.push("hello");<br /> std::cout<<stringStack.top()<<std::endl;<br /> stringStack.pop();<br /> stringStack.pop(); //會拋出std::out_of_range異常<br /> }catch(std::exception const& ex){ //捕捉到這個異常並列印出來<br /> std::cerr<<"Exception: "<<ex.what()<<std::endl;<br /> return EXIT_FAILURE;<br /> }<br />}
(2)改進1:指定棧的容量,要用到非類型模板參數。由於棧的容量固定,可以用數組來存放元素。
//stack2.h:容量受限的棧<br />#ifndef __STACK2_H__<br />#define __STACK2_H__<br />#include <stdexcept><br />template<typename T,int size><br />class Stack{<br /> T elems[size]; //由於容量受限,可用換成用數組來管理元素<br /> int numElems; //元素的當前總個數<br />public:<br /> Stack(); //建構函式<br /> void push(T const&); //壓入元素<br /> void pop(); //彈出元素<br /> T top() const; //返回棧頂元素<br /> bool empty() const{ //判斷棧是否為空白<br /> return numElems==0;<br /> }<br /> bool full() const{ //判斷棧是否已滿<br /> return numElems==size;<br /> }<br />};<br />template<typename T,int size><br />Stack<T,size>::Stack():numElems(0){ //初始時不含元素<br />//不做任何事<br />}<br />template<typename T,int size><br />void Stack<T,size>::push(T const& elem){<br /> if(numElems==size)<br /> throw std::out_of_range("Stack<T,size>::push(): stack is full");<br /> elems[numElems]=elem; //附加元素<br /> ++numElems; //增加元素個數<br />}<br />template<typename T,int size><br />void Stack<T,size>::pop(){<br /> if(numElems<=0)<br /> throw std::out_of_range("Stack<T,size>::pop(): empty stack");<br /> --numElems; //減少元素個數<br />}<br />template<typename T,int size><br />T Stack<T,size>::top() const{<br /> if(numElems<=0)<br /> throw std::out_of_range("Stack<>::top(): empty stack");<br /> return elems[numElems-1]; //返回末端元素<br />}<br />#endif
測試程式:
//stack2test.cpp:測試容量受限的Stack<br />#include <iostream><br />#include <string><br />#include <cstdlib><br />#include "stack2.h"<br />int main(){<br /> try{<br /> Stack<int,20> int20Stack; //可儲存20個int元素的棧<br /> Stack<int,40> int40Stack;<br /> Stack<std::string,40> stringStack;<br /> int20Stack.push(7);<br /> std::cout<<int20Stack.top()<<std::endl;<br /> int20Stack.pop();<br /> stringStack.push("hello");<br /> std::cout<<stringStack.top()<<std::endl;<br /> stringStack.pop();<br /> stringStack.pop();<br /> }catch(std::exception const& ex){<br /> std::cerr<<"Exception: "<<ex.what()<<std::endl;<br /> return EXIT_FAILURE;<br /> }<br /> return 0;<br />}
(3)改進2:可以指定棧內部使用的容器,還可以使 不同類型的棧之間能賦值。要用到模板模板參數。要定義一個賦值運算子的成員模板,它並不會覆蓋預設賦值運行符,對於相同類型棧之間的賦值,仍然會調用預設的賦值運行符。由於容器有兩個模板參數,一個是元素類型,一個是分配器類型,因此定義Stack的內部容器這個模板模板參數時,必須兩個模板參數都要有。若只定義一個元素類型的參數,你傳入容器(如vector,deque)時,並不能匹配。總之我們定義的模板模板參數必須與我們傳入的模板精確匹配。
//stack3.hpp:可以指定內部容器,並且不同類型的棧之間可以賦值的棧<br />#ifndef STACK_HPP<br />#define STACk_HPP<br />#include <deque><br />#include <stdexcept><br />#include <memory><br />template<typename T,template<typename ELEM,typename ALLOC=std::allocator<ELEM> ><br /> class CONT=std::deque><br />class Stack{<br /> CONT<T> elems; //存放元素的視窗<br />public:<br /> void push(T const&); //壓入元素<br /> void pop(); //彈出元素<br /> T top() const; //返回棧頂元素<br /> bool empty() const{ //判斷棧是否為空白<br /> return elems.empty();<br /> }<br />/* 這個賦值運算子是一個獨立的成員模板,它可以把Stack<T2,CONT2<ELEM2> >類型的棧賦值Stack<T,CONT<ELEM> >型的棧,<br /> 只要ELEM2型可以隱式轉換成ELEM型。它並沒有覆蓋預設賦值運行符,對於相同類型棧之間的賦值,仍然會調用預設的賦值運行符<br /> */<br /> template<typename T2,template<typename ELEM2,typename ALLOC=std::allocator<ELEM2> ><br /> class CONT2><br /> Stack<T,CONT>& operator=(Stack<T2,CONT2> const&);<br />};<br />/* 由於並不需要用到參數ELEM和ALLOC,故可以省略 */<br />template<typename T,template<typename,typename> class CONT><br />void Stack<T,CONT>::push(T const& elem){<br /> elems.push_back(elem); //把元素的拷貝添加到末端<br />}<br />template<typename T,template<typename,typename> class CONT><br />void Stack<T,CONT>::pop(){<br /> if(elems.empty())<br /> throw std::out_of_range("Stack<>::pop(): empty stack");<br /> elems.pop_back(); //刪除末端元素<br />}<br />template<typename T,template<typename,typename> class CONT><br />T Stack<T,CONT>::top() const{<br /> if(elems.empty())<br /> throw std::out_of_range("Stack<>::top(): empty stack");<br /> return elems.back(); //返回末端元素的拷貝<br />}<br />template<typename T,template<typename,typename> class CONT><br /> template<typename T2,template<typename,typename> class CONT2><br />Stack<T,CONT>& Stack<T,CONT>::operator=(Stack<T2,CONT2> const& rhs){<br /> if((void*)this==(void*)&rhs) //如果是自我賦值<br /> return *this;<br /> Stack<T2,CONT2> tmp(rhs);<br /> elems.clear(); //刪除所有現存的元素<br /> while(!tmp.empty()){<br /> //把rhs棧中元素拷貝到本棧中,並且元素的順序不變<br /> elems.push_front(tmp.top());<br /> tmp.pop();<br /> }<br /> return *this;<br />}<br />#endif
測試程式:
//stack3test.cpp:測試改進型棧的功能<br />#include <iostream><br />#include <string><br />#include <cstdlib><br />#include <vector><br />#include "stack3.hpp"<br />int main(){<br /> try{<br /> Stack<int> intStack; //int棧<br /> Stack<float> floatStack; //float棧</p><p> intStack.push(42);<br /> intStack.push(7);<br /> floatStack.push(7.7);<br /> floatStack=intStack; //不同類型的棧之間的賦值<br /> std::cout<<floatStack.top()<<std::endl;<br /> floatStack.pop();<br /> std::cout<<floatStack.top()<<std::endl;<br /> floatStack.pop();<br /> std::cout<<floatStack.top()<<std::endl;<br /> floatStack.pop();<br /> }catch(std::exception const& ex){<br /> std::cerr<<"Exception: "<<ex.what()<<std::endl;<br /> }<br /> Stack<int,std::vector> vStack; //使用vector作為內部容器的int棧<br /> vStack.push(42);<br /> vStack.push(7);<br /> std::cout<<vStack.top()<<std::endl;<br /> vStack.pop();<br /> return 0;<br />}