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 非常感谢,随时交流。

你可能感兴趣的:(C++)