• 类模板、Stack的类模板实现(自定义链栈方式,自定义数组方式)


    一、类模板

    类模板:将类定义中的数据类型参数化
    类模板实际上是函数模板的推广,可以用相同的类模板来组建任意类型的对象集合

    (一)、类模板的定义

    template  <类型形参表>
    class  <类名>
    {     //类说明体  };
    template  <类型形参表>
    <返回类型> <类名> <类型名表>::<成员函数1>(形参表)
    {     //成员函数定义体  }
    template  <类型形参表>
    <返回类型> <类名> <类型名表>::<成员函数2>(形参表)
    {     //成员函数定义体  }

    template  <类型形参表>
    <返回类型> <类名> <类型名表>::<成员函数n>(形参表)
    {     //成员函数定义体  }


    (二)、使用类模板

    类模板的实例化:用具体的数据类型替换模板的参数以得到具体的类(模板类)
    模板类也可以实例化为对象
    用下列方式创建类模板的实例:

    类名 <类型实参表>  对象名称;

    对于函数模板与类模板,模板参数并不局限于类型(类类型,基本类型,模板类实例),普通值也可以作为模板参数


    二、Stack类的模板实现

    前面曾经分别使用C/C++实现了一个链栈,栈中只能放进int类型数据,现在使用模板来重新实现Stack,可以存放多种数据类型,分别使用自定义链栈方式以及自定义数组实现。

    (一)、自定义链栈方式:

    stack.h:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
     
    /*************************************************************************
    > File Name: stack.h
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: 2012年11月03日 星期六 19时28分25秒
    ************************************************************************/

    #include<iostream>
    using namespace std;
    template < class T > class Node
    {
        //< >里面是模板参数,可以有多个,虽然T用class 声明,但可以是内建类型也可以是class类型
        //模板的定义一般写在头文件里
    public:

        Node(T invalue): m_Value(invalue), m_Next(NULL) {}
        ~Node();

        T getValue() const
        {
            return m_Value;
        }
        void setValue(T value)
        {
            m_Value = value;
        }

        Node < T > *getNext() const
        {
            return m_Next;
        }
        void setNext(Node < T > *next)
        {
            m_Next = next;
        }

    private:
        T m_Value;
        Node < T > *m_Next;
    };

    template < class T > Node < T >::~Node()
    {
        if (m_Next)
        {
            delete m_Next;  //自动内存管理,接着找到m_Next指向的下一个结点,一直找到最后的一个结点
            //故先释放最后一个结点(当然是最先压栈的结点),然后依次返回释放每一个途中的结点
        }
    " deleted " << endl;
    }

    template < class T > class Stack
    {

    public:
        Stack(): m_Head(NULL), m_Count(0) {}
        ~Stack()
        {
            delete m_Head;  //自动内存管理
        }
        void push(const T &t);
        T pop();
        T top() const;
        int count() const;
    private:
        Node < T > *m_Head;
        int m_Count;
    };

    template < class T > void Stack < T >::push(const T &value)
    {
        Node < T > *newNode = new Node < T > (value);
        newNode->setNext(m_Head);
        m_Head = newNode;
        ++m_Count;
    }

    template < class T > T Stack < T >::pop()
    {
        Node < T > *popped = m_Head;
        if (m_Head != NULL)
        {

            m_Head = m_Head->getNext();
            T retval = popped->getValue();
            popped->setNext(NULL);
            delete popped;
            --m_Count;
            return retval;
        }
        return 0;
    }

    template < class T > inline T Stack < T >::top() const
    //模板前缀template < class T >  || 函数限定符inline  函数返回值T ||
    //命名空间前缀 Stack < T > //一个类型  || 函数名(函数参数)const 限定符
    {
        return m_Head->getValue();

    }

    template < class T > inline int Stack < T >::count() const
    {
        return m_Count;
    }

    main.cpp:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #include "stack.h"

    int main(void)
    {
        Stack < int >intstack1, intstack2;

        int val;
        for (val = 0; val < 4; ++val)
        {
            intstack1.push(val);
            intstack2.push(2 * val);
        }

        while (intstack1.count())
        {
            val = intstack1.pop();
            cout << val << endl;
        }

        Stack < char >stringstack;

        stringstack.push('A');
        stringstack.push('B');
        stringstack.push('C');

        char val2;
        while (stringstack.count())
        {
            val2 = stringstack.pop();
            cout << val2 << endl;
        }
        cout << "Now intstack2 will be destructed." << endl;
        return 0;
    }


    可以看到虽然intstack2 没有pop 出元素,但程序结束时,局部对象会被析构,调用析构函数,在析构函数内delete 头指针,顺藤摸瓜一直找到最后一个节点,即首先压栈的节点,依次返回释放掉。


    (二)、自定义数组方式

    Stack2.h:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    #ifndef _STACK2_H_
    #define _STACK2_H_

    #include <exception>

    template <typename T, int MAX_SIZE>
    class Stack2
    {
    public:
        Stack2();
        ~Stack2();

        void Push(const T &elem);
        void Pop();
        T &Top();
        const T &Top() const;
        bool Empty() const;
    private:
        T *elems_;
        int top_;
    };

    template <typename T, int MAX_SIZE>
    Stack2<T, MAX_SIZE>::Stack2() : top_(-1)
    {
        elems_ = new T[MAX_SIZE];
    }

    template <typename T, int MAX_SIZE>
    Stack2<T, MAX_SIZE>::~Stack2()
    {
        delete[] elems_;
    }

    template <typename T, int MAX_SIZE>
    void Stack2<T, MAX_SIZE>::Push(const T &elem)
    {
        if (top_ + 1 >= MAX_SIZE)
            throw out_of_range("Stack2<>::Push() Stack2 full");

        elems_[++top_] = elem;
    }

    template <typename T, int MAX_SIZE>
    void Stack2<T, MAX_SIZE>::Pop()
    {
        if (top_ + 1 == 0)
            throw out_of_range("Stack2<>::Push() Stack2 empty");

        --top_;
    }

    template <typename T, int MAX_SIZE>
    T &Stack2<T, MAX_SIZE>::Top()
    {
        if (top_ + 1 == 0)
            throw out_of_range("Stack2<>::Push() Stack2 empty");

        return elems_[top_];
    }

    template <typename T, int MAX_SIZE>
    const T &Stack2<T, MAX_SIZE>::Top() const
    {
        if (top_ + 1 == 0)
            throw out_of_range("Stack2<>::Push() Stack2 empty");

        return elems_[top_];
    }

    template <typename T, int MAX_SIZE>
    bool Stack2<T, MAX_SIZE>::Empty() const
    {
        return top_ + 1 == 0;
    }
    #endif // _STACK2_H_

    main.cpp:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include "Stack2.h"
    #include <iostream>
    #include<string>
    using namespace std;

    int main(void)
    {
        Stack2<int, 5> s;
        s.Push(1);
        s.Push(2);
        s.Push(3);

        while (!s.Empty())
        {
            cout << s.Top() << endl;
            s.Pop();
        }
        return 0;
    }

    输出为 3 2 1

    注意,用数组实现时pop 操作并没有删除元素的操作,只是移动了top 指针,下次push 的时候直接覆盖即可。再者因为实现了Top 返回栈顶元素,故pop 没有返回值。


    参考:

    C++ primer 第四版
    Effective C++ 3rd
    C++编程规范

  • 相关阅读:
    poj2954
    bzoj1863
    bzoj2002
    bzoj1389
    [POJ3041] Asteroids(最小点覆盖-匈牙利算法)
    [POJ2594] Treasure Exploration(最小路径覆盖-传递闭包 + 匈牙利算法)
    [POJ2446] Chessboard(二分图最大匹配-匈牙利算法)
    [luoguP1266] 速度限制(spfa)
    [luoguP1186] 玛丽卡(spfa)
    [luoguP1027] Car的旅行路线(Floyd)
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471167.html
Copyright © 2020-2023  润新知