面向对象几种类模板整理

1.Node类(节点类)

数据成员:

T data;   //存放节点数据

Node<T> *next;  //指向下一个类

注意:

需要在Node类里声明LinkList为友元类

friend class LinkList<T>;

template <typename T> class Node    // 结点类模板
{
public:
    Node() : next(NULL) {}//构造函数
    Node(const T &t) : data(t), next(NULL) {}//构造函数
    Node(const Node<T> &node) : data(node.data), next(NULL) {}//拷贝构造函数
    Node<T> & operator=(const Node<T> &node)
    {
        data = node.data;
        return *this;
    }
    friend class LinkList<T>;//设置成一个友元类
private:
    T data;
    Node<T> *next;
};

 

2.LinkList类(链表类)

数据成员:

Node<T> *head; //头节点

int num;  //节点个数

注意:

构造函数需要按照节点个数申请一个个的空间放置节点,插在head上

拷贝构造函数可以利用赋值函数调用*thiis=t;

析构函数需要一个个把节点释放掉,从头释放,要保证不会丢失头节点所以释放时要先把首节点指向下一节点,释放指向首节点的p

链表要注意添加顺序!赋值时不能从头上添加节点,append函数是从尾部添加节点,要用

while(p->next!=NULL)

      p = p->next;

每次都指向链表的尾部,然后为下一空指针申请空间,把下下指针指向NULL;

重载<<函数,不能设计为成员函数,函数头如下

ostream & operator<<(ostream &out, const LinkList<T> &t)

{

out<<.......

return out;

}

 

 

template <typename T> class LinkList                // 单向链表类模板
{
public:
    LinkList(int n=0, const T *x=NULL);             // ① 构造函数
    LinkList(const LinkList<T> &link);        // ② 拷贝构造函数
    virtual ~LinkList();                                    // ③ 析构函数
    LinkList<T> & operator=(const LinkList<T> &link);
                                                                 // ④ 赋值运算符函数
    void FreeList();                                        // ⑤ 释放所有结点
    void Append(const T &t);                             // ⑥ 追加新的尾结点
    virtual void ShowList(ostream &out)const;    // ⑦ 输出
protected:
    Node<T> *head;
};                                                    // ⑧ 重载operator<< 运算符


template <typename T>
LinkList<T>::LinkList(int n, const T *x):head(NULL)  //构造函数
{
    Node<T> *p;
    for(int i=0;i<=n;i++)
    {
        p=new Node<T>;
        if(x!=NULL)
            p->data=x[i];
        p->next=head;
head
=p; } } template <typename T> LinkList<T>::LinkList(const LinkList<T> &link):head(NULL) { *this=link; } template<typename T> LinkList::~LinkList() { FreeList(); } template <typename T> LinkList<T> & LinkList<T>::operator=(const LinkList<T> &link) { if(&link==this) { return *this; } FreeList(); for(Node<T> *p=link.head;p!=NULL;p=p->next) ( Append(p->data); ) return *this; } template <typename T> // ④ 赋值运算符函数 void LinkList<T>::FreeList() // ⑤ 释放所有结点 { Node<T> *p; while(head!=NULL) { p=head; head=head->next; delete p; } } template <typename T> void LinkList<T>::Append(const T &t)// ⑥ 追加新的尾结点 { if(head==NULL) { head=new Node<T>(t); head->next=NULL; return; } Node<T> *p; p=head; while(p->next!=NULL) {p=p->next;} p->next=new Node<T>(t); p->next->next=NULL; } template <typename T> void LinkList<T>::ShowList(ostream &out)const// ⑦ 输出 { out<<"head "; for(Node<T> *p=head;p!=NULL;p=p->next) { out<<"->"<<p->data; } out<<"->NULL"; template <typename T> ostream & operator<<(ostream &out,const LinkList<T> &link) { link.ShowList(out); return out; }

3.Vector类(向量类)

数据成员:

int n;   //向量维度

double *x;  //存向量数据

 注意:(大多数最后一题都这么搞,重点看赋值函数,拷贝构造函数,重载运算符函数)

构造函数,存向量数据的double型指针x申请的空间需要根据维度n来确定

在存入向量数据时要验证所得接收指针是否为NULL

函数头:Vector::Vector(int dim=0, const double *x=NULL) : n(dim), p(NULL)

析构函数,判断指针是否为空然后delete删除,需要把维度置0

函数头:Vector::virtual ~Vector()

赋值函数,首先判断两指针指向(而非指针所指内容)是否相等,相同返回this指针所指内容(本对象)不同则依照【先删除原有空间】->【通过维度新值申请新的空间】->【循环语句一个个拷贝】

函数头:Vector&Vector::operator=(const Vector & t)

拷贝构造函数,指针不可以更改指向,this常指针,所以更改指针所指内容,利用赋值函数

函数头:Vector::Vector(const Vector & t):n(0),p(NULL)

其他成员函数,需要类有较好的容错性能,就要在成员函数设计时时刻检验x是否为空指针以及维度

n是否小于等于0,例如:average函数若维度n为0(构造函数的设计使得n不可能小于0,且n为0,p为空)就直接返回NULL(NULL与整型0区别在于能表示地址,本身也可以作为整型0使用);max,min,range函数也是在n==0时直接返回0

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4 
 5 class Vector
 6 {
 7 public:
 8     Vector(int dim=0, const double *x=NULL) : n(dim), p(NULL)
 9     {
10         if(n<=0)
11         {
12             n = 0; return;
13         }
14         p = new double[n];
15         for(int i=0; i<n; i++)
16             p[i] = (x==NULL)? 0 : x[i];
17     }
18     Vector(const Vector &v) : n(0), p(NULL)
19     {
20         *this = v;
21     }
22 
23     virtual ~Vector()
24     {
25         if(p!=NULL) delete [] p;
26         n = 0;
27         p = NULL;
28     }
29     Vector & operator=(const Vector &v)
30     {
31         if(this == &v)
32             return *this;
33         if(p!=NULL) delete [] p;
34         p = NULL;
35         n = 0;
36         if(v.n<=0)
37             return *this;
38         p = new double[n];
39         for(int i=0; i<n; i++)
40             p[i] = v.p[i];
41         return *this;
42     }
43     double average() const
44     {
45         double y=0;
46         for(int i=0; i<n; i++)
47             y += p[i];
48         if(n>0)
49             y /= n;;
50         return y;
51     }
52     double max() const
53     {
54         if(n==0) return 0;
55         double max = p[0];
56         for(int i=1; i<n; i++)
57             if(p[i]>max) max = p[i];
58         return max;
59     }
60     double min() const
61     {
62         if(n==0) return 0;
63         double min = p[0];
64         for(int i=1; i<n; i++)
65             if(p[i]<min) min = p[i];
66         return min;
67     }
68     double range() const    // 极差(range): 最大值-最小值
69     {
70         if(n==0) return 0;
71         double min, max;
72         min = max = p[0];
73         for(int i=1; i<n; i++)
74         {
75             if(p[i]<min) min = p[i];
76             if(p[i]>max) max = p[i];
77         }
78         return max-min;
79     }
80 private:
81     int n;
82     double *p;
83 };
84 
85 int main()
86 {
87     double array[] = {85, 73, 60, 98, 86, 76, 85, 90, 93, 80};
88     int n = sizeof(array)/sizeof(*array);
89     Vector v(n, array);
90     cout << "范围: [" << v.min() << ", " << v.max()
91           << "],\t极差: " << v.range()
92           << ",\t平均值: " << v.average() << endl;
93     return 0;
94 }

 

4.Matrix类

数据成员:

int row,col;

double *x;  //存放矩阵数据

注意:

给矩阵里存数据遍历用以下循环

for(int i=row*col-1;i>=0;i--)

5.Stack类

数据成员:

T *x;   //栈的首地址

int top,max;   //栈顶位置,表示下标用于指针间指(-1表示栈为空),栈的最大容量(创建对象时一旦确定不可更改)

注意:做栈的pop和push操作都是针对栈顶(栈只有一个出入口)

push函数返回bool型值,需要验证当前是否已经满栈

pop函数需要验证栈是否为空

 

template <typename T> class Stack
{
public:
    Stack(int Max=5): x(NULL),top(-1),max(0)    // 构造函数
    {
        if(Max<=0) return;
        x = new T[max=Max];
    }
    Stack(const Stack &s): x(NULL),top(-1),max(0)
    {
        *this = s;
    }
    ~Stack()
    {
        if(x!=NULL) delete [] x;
        top = -1;
        max = 0;
    }
    Stack & operator=(const Stack &s)
    {
        if(this==&s) return *this;
        if(x!=NULL) delete [] x;
        top = s.top;
        max = s.max;
        if(s.x!=NULL)
        {
            x = new T[max];
            for(int i=0; i<=top; i++)            // 栈顶以上的无须复制
                x[i] = s.x[i];
        }
        else
            x = NULL;
    }
    int Size() const;            // 获取栈中当前拥有的元素个数
    bool Empty() const;        // 当栈为空时返回true,否则返回false
    bool Top(T &t) const;    
    bool Push(const T &t);    
    bool Pop(T &t);
private:
    T *x;
    int top, max;
};
template <typename T> int Stack<T>::Size() const
{
    return top + 1;
}
template <typename T> bool Stack<T>::Empty() const
{
    return top == -1;
}
template <typename T> bool Stack<T>::Top(T &t) const
{
    if(top >= 0)
    {
        t = x[top];
        return true;
    }
    return false;
}
template <typename T> bool Stack<T>::Push(const T &t)
{
    if(top < max-1)
    {
        x[++top] = t;
        return true;
    }
    return false;
}
template <typename T> bool Stack<T>::Pop(T &t)
{
    if(top >= 0)
    {
        t = x[top--];
        return true;
    }
    return false;
}

 

 

6.AutoLink类

7.Complex类(复数类) 

数据成员:

double re, im;

注意:数学函数double atan2(double y, double x);当x≠0时返回y/x的反正切值,当x=0时返回π/2

或-π/2(正负号与y同号)

复数加法是x1*x1-y1*y1,减法x1y2+x2y1

(a+bi)(c+di)=(ac-bd)+(bc+ad)i

 Complex.h
#include <iostream>
#include <cmath>
using namespace std;

class Complex
{
public:
    Complex(double real=0, double imag=0):re(real),im(imag){}

    double & Real(){ return re; }
    double & Imag(){ return im; }
    double Angle() const { return atan2(im, re); }
    double Abs() const { return sqrt(re*re + im*im); }

    friend Complex operator+(const Complex &c1, const Complex &c2)
    {
        Complex result(c1);
        result.re += c2.re;
        result.im += c2.im;
        return result;
    }

    friend Complex operator*(const Complex &c1, const Complex &c2)
    {
        Complex result;
        result.re = c1.re*c2.re - c1.im*c2.im;
        result.im = c1.re*c2.im + c1.im*c2.re;
        return result;
    }

    Complex & operator*=(const Complex &c)
    {
        double x = re*c.re - im*c.im;
        im = re*c.im + im*c.re;
        re = x;
        return *this;
    }

    friend ostream & operator<<(ostream &out, const Complex &c)
    {
        out << '(' << c.re << ", " << c.im << ')';
        return out;
    }
    
protected:
    double re, im;
};

 

 

 

posted @ 2020-11-30 19:03  rippleD  阅读(19)  评论(0)    收藏  举报