栈的模拟与评析

来源:互联网 发布:美国三季度经济数据 编辑:程序博客网 时间:2024/04/28 20:35

1  我的简单模拟

Code:
  1. template<typename T>          
  2. class stack       
  3. {       
  4. public:       
  5.     void push(T const& elem);       
  6.     void pop();       
  7.     T top()const;       
  8.     bool empty()const      
  9.     {       
  10.         return _stack.empty();       
  11.     }       
  12.     T& operator[](int i)       
  13.     {       
  14.         return _stack[i];       
  15.     }       
  16.     bool operator == (stack<T>& rhs)       
  17.     {       
  18.         return _stack == rhs._stack;       
  19.     }       
  20.     friend bool operator != (stack<T>& lhs,stack<T>& rhs);       
  21.     friend bool operator < (stack<T>& lhs,stack<T>& rhs);       
  22.     friend bool operator <= (stack<T>& lhs,stack<T>& rhs);       
  23.     friend bool operator > (stack<T>& lhs,stack<T>& rhs);       
  24.     friend bool operator >= (stack<T>& lhs,stack<T>& rhs);       
  25. private:       
  26.     vector<T> _stack;       
  27. };       
  28. template<typename T>       
  29. void stack<T>::push(T const& elem)       
  30. {       
  31.     _stack.push_back(elem);       
  32. }       
  33. template<typename T>       
  34. void stack<T>::pop()       
  35. {       
  36.     if (_stack.empty())       
  37.     {       
  38.         throw out_of_range("stack<>::pop():empty stack");       
  39.     }       
  40.     _stack.pop_back();       
  41. }       
  42. template<typename T>         
  43. T stack<T>::top()const      
  44. {       
  45.     if (_stack.empty())       
  46.     {       
  47.         throw out_of_range("stack<>::pop():empty stack");       
  48.     }       
  49.     return _stack.back();       
  50. }       
  51. template<typename T>        
  52. bool operator != (stack<T>& lhs,stack<T>& rhs)       
  53. {       
  54.     return !(lhs == lhs);       
  55. }       
  56. template<typename T>        
  57. bool operator < (stack<T>& lhs,stack<T>& rhs)       
  58. {       
  59.     return lhs._stack < rhs._stack;       
  60. }       
  61. template<typename T>       
  62. bool operator <= (stack<T>& lhs,stack<T>& rhs)       
  63. {       
  64.     return lhs._stack <= rhs._stack;       
  65. }       
  66. template<typename T>       
  67. bool operator > (stack<T>& lhs,stack<T>& rhs)       
  68. {       
  69.     return !(lhs <= rhs);       
  70. }       
  71. template<typename T>       
  72. bool operator >= (stack<T>& lhs,stack<T>& rhs)       
  73. {       
  74.     return !(lhs < rhs)       
  75. }    

 2 《C++ STL中文版》上栈的源码

Code:
  1. #include <iostream>   
  2. #include <deque>   
  3. #include <assert.h>   
  4. #include <vector>   
  5. #include <list>   
  6. using namespace std;   
  7. template < typename T,typename C = deque<T> >   
  8. class stack   
  9. {   
  10. public:   
  11.     typedef typename C container_type;   
  12.     typedef typename C::value_type value_type;   
  13.     typedef typename C::size_type size_type;   
  14.     explicit stack(const C& cont):_stack(cont){}//构造函数   
  15.     stack():_stack(){}   
  16.     bool empty()const{return (_stack.empty());}   
  17.     size_type size()const{return (_stack.size());}   
  18.     value_type& top(){return (_stack.back());}   
  19.     const value_type& top()const{return (_stack.back());}   
  20.     void push(const value_type& elem)   
  21.     {   
  22.         _stack.push_back(elem);   
  23.     }   
  24.     void pop()   
  25.     {   
  26.         _stack.pop_back();   
  27.     }   
  28.     bool Eq(const stack<T,C>& X)const  
  29.     {   
  30.         return (_stack == X._stack);   
  31.     }   
  32.     bool Lt(const stack<T,C>& X)const  
  33.     {   
  34.         return (_stack < X._stack);   
  35.     }   
  36. protected:   
  37.     deque<T> _stack;   
  38. };   
  39. template <typename T,typename C>   
  40. inline bool operator == (const stack<T,C>& lhs,const stack<T,C>& rhs)   
  41. {   
  42.     return lhs.Eq(rhs);   
  43. }   
  44. template <typename T,typename C>   
  45. inline bool operator != (const stack<T,C>& lhs,const stack<T,C>& rhs)   
  46. {   
  47.     return !(lhs == rhs);   
  48. }   
  49. template <typename T,typename C>   
  50. inline bool operator < (const stack<T,C>& lhs,const stack<T,C>& rhs)   
  51. {   
  52.     return lhs.Lt(rhs);   
  53. }   
  54. template <typename T,typename C>   
  55. inline bool operator > (const stack<T,C>& lhs,const stack<T,C>& rhs)   
  56. {   
  57.     return rhs < lhs;   
  58. }   
  59. template <typename T,typename C>   
  60. inline bool operator <= (const stack<T,C>& lhs,const stack<T,C>& rhs)   
  61. {   
  62.     return !(rhs < lhs);   
  63. }   
  64. template <typename T,typename C>   
  65. inline bool operator >= (const stack<T,C>& lhs,const stack<T,C>& rhs)   
  66. {   
  67.     return !(lhs < rhs);   
  68. }   
  69. int main()   
  70. {   
  71.     typedef allocator<char> Myal;   
  72.     typedef deque<char,Myal> Myimpl;   
  73.     typedef stack<char,Myimpl> Mycont; //定义一个以双队列为容器的栈   
  74.     typedef list<char,Myal> Myimpl2;   
  75.     typedef stack<char,Myimpl2> Mycont2; //定义一个以链表为容器的栈   
  76.     typedef vector<char,Myal> Myimpl3;   
  77.     typedef stack<char,Myimpl3> Mycont3; //定义一个以向量为容器的栈   
  78.     Mycont::container_type *p_cont = (Myimpl *)0; //容器指针   
  79.     Mycont::value_type *p_val = (char *) 0; //类型指针   
  80.     Mycont::size_type *p_size = (size_t *)0;    
  81.     Mycont v0(Myimpl(3,'x')),v0a; //v0中有三个元素 均为x0a为空   
  82.     Mycont2 v1; //空   
  83.     Mycont3 v2; //空   
  84.     assert(v0.size() == 3 && v0.top() == 'x'); //条件满足   
  85.     assert(v0a.empty()); //条件满足   
  86.     v0 = v0a;//清空v0   
  87.     v0.push('a'); //此时v0中有1个元素 栈顶为a   
  88.     assert(v0.size() == 1 && v0.top() == 'a'); //条件满足   
  89.     v0.push('b'); //此时v0中有两个元素 栈顶为b   
  90.     assert(v0.size() == 2 && v0.top() == 'b'); //条件满足   
  91.     v0.push('c'); //此时v0中有三个元素 栈顶为c   
  92.     assert(v0.size() == 3 && v0.top() == 'c'); //条件满足   
  93.     assert(v0 == v0 && v0a < v0); //测试 == 和 < 由于v0a为空 故条件满足   
  94.     assert(v0 != v0a && v0 > v0a); //测试 != 和 > 条件满足   
  95.     assert(v0a <= v0 && v0 >= v0a); //测试 <= ,>= 条件满足   
  96.     v0.pop(); //出栈 v0中有两个元素 栈顶为b   
  97.     assert(v0.top() == 'b'); //条件满足   
  98.     v0.pop(); //出栈 此时v0中有一个元素 栈顶为a   
  99.     assert(v0.top() == 'a'); //条件满足   
  100.     v0.pop(); //出栈 栈空   
  101.     assert(v0.empty()); //条件满足   
  102.     cout << "SUCCESS testing <stack>" << endl;   
  103.     system("pause");   
  104.     return 0;   
  105. }  

3 我的程序与源码的对比

 ① 就整体模板而言

源码就比我稍胜一筹,它给用户提供了更多的选择,即容许用户提供自己的容器类型,并且源码还提供了默认的容器类型。即:双端队列。

 ② 从效率而言

 源码基本上把所有的函数均定义为了内敛函数,并且这些函数也符合内敛的规则。而我的函数大部分都别我定义成了友元函数。效率上应该不如源码。

 ③ 从封装性而言

 源码的封装性比我的好,因为我的大部分函数均定义为了友元,这样就降低了类的封装性,而源码的实现方法比较好,它仅仅为类增加了两个成员函数,然后其他的函数均在类外通过对象调用这两个函数来实现功能。封装性提升了。

 ④ 就功能而言

 源码的功能定时齐全了,不但栈的所有功能均已实现,还为栈定义了几种类型,如栈内容器类型,元素类型,大小类型等。

 ⑤ 成员的属性

  容器在我的程序中为私有成员,而在源码中为保护成员,看似源码在为其它类派生该类做了准备。这确实考虑周到,真没想到这点。

 ⑥ 我的优点

  源码唯一没有用的就是异常,并且在入栈或是返回栈顶元素的时候没有进行栈空检验(这里应该抛出一个out_of_range();异常),我觉得这点很重要,应该有个提示语告诉用户,否则用户还不知道发生了什么事情呢。。

总结:

1 在写程序时应该注意时常站在用户的角度去考虑问题,要一切为用户,方便用户。毕竟它是才真正使用我们的设计的人,应该让我们的接口易于使用,不容易被误用。另:接口应该符合用户的习惯,如求大小的size(),求栈顶的top()这些都是用户习惯了的函数,若我们冒然改变,用户定是很是不习惯,难免会有抱怨。。

2 在功能的设计上应该齐全,同样要站在用户的角度,考虑用户会用到那些功能,以及这些功能常用的函数名是什么。

3 在效率上,应该时刻考虑到效率的存在,不能只为功能而设计,效率却也很重要。

4 在类的封装性啊。类的封装性是C++里一个重要的性质,也是面向对象的一个重要性质,这个不能忽略,应该时刻考虑到封装性,若是封装性都给忽略了,一切为了设计而设计,那和面向过程也快没什么区别了。。

5 在错误判断上,对于一个功能的设计,我们应该时刻考虑到用户会犯的错误以及处理的办法。或是警告用户错误的地方并推出程序,或是给用户一个选择的机会等。否则用户会为这莫名奇妙的错误而犯愁呢。。呵呵。。

 6 代码的复用性

 应该考虑到代码的复用性,不能只为设计而设计,在实际工作呢。。用到以前的模块或是代码应该是很有很能的,而在C++中的复用性有: 1 类的继承,即我们可以继承一个已有的类,来复用已有类的接口或是成员,2 组合 我们可以将一个已有类的对象作为新类的一个成员来复用 3 函数复用,模块复用 等。。。故复用性也很重要不可忽略。

原创粉丝点击