zoukankan      html  css  js  c++  java
  • C++采用模板实现栈的方法

    今天又看了遍《effective C++》,手动实现了一下条款42中的栈,贴出来当博客的处女贴。

    首先栈的声明如下,采用了模板传入类型,而栈的底层采用是个链表。

    // stack.h
    // by Chwen 2014-10-27 
    
    #include<stdio.h>
    #include <stdlib.h>
    #include <iostream>
    
    using namespace std;
    
    // 栈声明
    
    template<typename T>
    class Stack
    {
    public:
        Stack();
        ~Stack();
    
        void push(const T& node);
        T Top();
        void pop();
        int size()const;
        bool Empty() const;
        void clear();
    
    private:
        struct StackNode
        {
            T data;
            StackNode* next;
            StackNode(const T& Newdata, StackNode* nextNode)
                :data(Newdata),next(nextNode)
            {}
        };
       
        StackNode * top;
        // 防止默认拷贝和默认赋值
        Stack(const Stack& rhs);
        Stack& operator=(const Stack& rhs);
        int mySize;
    };

      而对应的cpp实现如下:

    // stack.cpp
     
    #include "stack.h"
    using namespace std;
    
    
    // 栈实现
    
    template<typename T>
    Stack<T>::Stack()
        :top(nullptr),mySize(0)
    {
    
    }
    
    template<typename T>
    Stack<T>::~Stack()
    {
        clear();
    }
    
    template<typename T>
    void Stack<T>::push(const T& node)
    {
        top = new StackNode(node,top);
        mySize ++;
    }
    
    template<typename T>
    T Stack<T>::Top()
    {
        if (Empty())
        {
            _DEBUG_ERROR("Error, stack is empty!");
        }
        return top->data;
    }
    
    template<typename T>
    void Stack<T>::pop()
    {
        if (Empty())
        {
            _DEBUG_ERROR("Error, stack is empty!");
        }
        StackNode* topOfStack = top;
        top = top->next;
        delete topOfStack;
        topOfStack = nullptr;
        mySize --;
        return;
    }
    
    template<typename T>
    bool Stack<T>::Empty() const
    {
        return top == nullptr;
    }
    
    template<typename T>
    void Stack<T>::clear()
    {
        while (top)
        {
            StackNode* topOfStack = top;
            top = top->next;
            delete topOfStack;
    
        }
        mySize = 0;
    }
    template<typename T>
    int Stack<T>::size()const
    {
        return mySize;
    }

    以上即是采用模板实现的栈的所有代码,可以实现栈的push,  pop, top, clear 等操作。

    以下写了一个简单的测试代码:

    void funv()
    {
     
        Stack<int> s;
    
        for(int i = 0; i < 10; ++i)
        {
            s.push(i);
        }
        for(int j = s.size()-1 ; j >= 0; --j)
        {
            cout<< "node: " << s.Top() <<endl;
            s.pop();
        }
    
        s.clear();
    
    }

    int main ()
    {
      funv();
      getchar();
      return 0;
    }


    之后effective C++指出了另一种更精巧的方式实现,即私有继承。

    代码实现如下:

    // stack.h
    // by Chwen 2014-10-27 
    #include<stdio.h>
    #include <stdlib.h>
    #include <iostream>
    
    class commonStack
    {
    protected:
        commonStack();
        ~commonStack();
    
        void push(void* node);
        void* Top();
        void pop();
        int size()const;
        bool Empty() const;
        void clear();
    
        
    private:
        struct StackNode
        {
            void* data;
            StackNode* next;
            StackNode(void* Newdata, StackNode* nextNode)
                :data(Newdata),next(nextNode)
            {}
        };
    
        StackNode * top;
        // 防止默认拷贝和默认赋值
        commonStack(const commonStack& rhs);
        commonStack& operator=(const commonStack& rhs);
        int mySize;
    };
    
    
    template <typename T>
    class Stack:private commonStack
    {
    public:
        void push(T * ty){commonStack::push(static_cast<void*>(ty));}
        T* top(){return static_cast<T*>(commonStack::Top());}
        void pop(){return commonStack::pop();}
        int size(){return commonStack::size();}
        bool Empty()const{ return commonStack::Empty(); }
        void clear(){return commonStack::clear();}
     
    
    };

    对应的cpp 如下:

     
    #include "stack.h"
     
    using namespace std;
    
    commonStack::commonStack()
        :top(nullptr),mySize(0)
    {
    
    }
    
     
    commonStack::~commonStack()
    {
        clear();
    }
    
     
    void commonStack::push(void* node)
    {
        top = new StackNode(node,top);
        mySize ++;
    }
    
     
    void* commonStack::Top()
    {
        if (Empty())
        {
            _DEBUG_ERROR("Error, stack is empty!");
        }
        return top->data;
    }
    
     
    void commonStack::pop()
    {
        if (Empty())
        {
            _DEBUG_ERROR("Error, stack is empty!");
        }
        StackNode* topOfStack = top;
        top = top->next;
        delete topOfStack;
        topOfStack = nullptr;
        mySize --;
        return;
    }
    
     
    bool  commonStack::Empty() const
    {
        return top == nullptr;
    }
     
    void commonStack::clear()
    {
        while (top)
        {
            StackNode* topOfStack = top;
            top = top->next;
            delete topOfStack;
    
        }
        mySize = 0;
    }
     
    int commonStack::size()const
    {
        return mySize;
    }

    这里commonStack将原模板类的T改为了void*, 之后使用protected保护该类不会被其他不明群众调用,而是给出了一个模板接口类私有继承这个类,这样一来,既起到了保护作用,又在低损耗的情况下给出了方便易用的接口,巧夺天工的设计。

    测试代码如下:

    void funcInt()
    {
        int* a[10];
        for(int i = 0 ; i < 10; ++i)
        {
            a[i] = new int(i);
        }
    
        Stack<int> s;
        
        for(int j = 0 ; j < 10; ++j)
        {
            s.push(a[j]);
        }
    
        int k = s.size();
        int* t = s.top();
        s.pop();
        if(s.Empty())
        {
            cout<<"empty"<<endl;
        }
        s.clear();
        
        for(int i = 0 ; i < 10; ++i)
        {
            delete a[i] ;
        }
    
    }
    
    void funcString()
    {
        string* str[10];
        for(int i = 0 ; i < 10; ++i)
        {
            str[i] = new string("a");
        }
    
        Stack<string> s;
    
        for(int j = 0 ; j < 10; ++j)
        {
            s.push(str[j]);
        }
    
        int k = s.size();
        string* t = s.top();
        s.pop();
        if(s.Empty())
        {
            cout<<"empty"<<endl;
        }
        s.clear();
    
        for(int i = 0 ; i < 10; ++i)
        {
            delete str[i] ;
        }
    }
    
    int main ()
    {
        funcInt();
        funcString();
        getchar();
        return 0;
    }

    测试代码没有输出,可以断点看数据。

    之后我又去看了一眼STL对栈的实现,它默认使用deque作为栈的底层实现。

    template<class _Ty,
    class _Container = deque<_Ty> >
    
    class stack
    {
    // 栈实现
    }

    调用的时候直接std::stack<int> 即默认使用deque作为栈底层容器。

    用户也可以指定其他方式,比如std::stack<int, std::list<int> >, 这样就使用了list作为栈的底层容器。

    让我感到awesome的是STL实现的精巧和灵活性,居然是可指定底层的一种实现方法,太精巧了。回头再去看一下《STL源码剖析》。

    只罗列了代码,没太详细的介绍原理,感兴趣的可以直接去看《effective C++》和《STL源码剖析》,以及STL的stack代码。

    引用请注明出处,http://www.cnblogs.com/chwen/p/4055474.html 非常感谢,随时交流。

  • 相关阅读:
    11. Container With Most Water(装最多的水 双指针)
    64. Minimum Path Sum(最小走棋盘 动态规划)
    数组相关
    88. Merge Sorted Array(从后向前复制)
    京东AI平台 春招实习生面试--NLP(offer)
    54. Spiral Matrix(矩阵,旋转打印)
    48. Rotate Image(旋转矩阵)
    春招实习--阿里 蚂蚁金服 支付宝 机器学习面试
    26. Remove Duplicates from Sorted Array(删除排序数组中的重复元素,利用排序的特性,比较大小)
    7. Reverse Integer(翻转整数)
  • 原文地址:https://www.cnblogs.com/chwen/p/4055474.html
Copyright © 2011-2022 走看看