线性表——数组描述

异常类的定义

// exception classes for various error types

#ifndef myExceptions_
#define myExceptions_
#include <string>

using namespace std;

// illegal parameter value
class illegalParameterValue
{
   public:
      illegalParameterValue(string theMessage = "Illegal parameter value")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// illegal input data
class illegalInputData
{
   public:
      illegalInputData(string theMessage = "Illegal data input")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// illegal index
class illegalIndex
{
   public:
      illegalIndex(string theMessage = "Illegal index")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// matrix index out of bounds
class matrixIndexOutOfBounds
{
   public:
      matrixIndexOutOfBounds
            (string theMessage = "Matrix index out of bounds")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// matrix size mismatch
class matrixSizeMismatch
{
   public:
      matrixSizeMismatch(string theMessage =
                   "The size of the two matrics doesn't match")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// stack is empty
class stackEmpty
{
   public:
      stackEmpty(string theMessage =
                   "Invalid operation on empty stack")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// queue is empty
class queueEmpty
{
   public:
      queueEmpty(string theMessage =
                   "Invalid operation on empty queue")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// hash table is full
class hashTableFull
{
   public:
      hashTableFull(string theMessage =
                   "The hash table is full")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// edge weight undefined
class undefinedEdgeWeight
{
   public:
      undefinedEdgeWeight(string theMessage =
                   "No edge weights defined")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};

// method undefined
class undefinedMethod
{
   public:
      undefinedMethod(string theMessage =
                   "This method is undefined")
            {message = theMessage;}
      void outputMessage() {cout << message << endl;}
   private:
      string message;
};
#endif

抽象类型linearList

#ifndef LINEARLIST_H_INCLUDED
#define LINEARLIST_H_INCLUDED

#include<iostream>
using namespace std;

template<class T>
class linearList{
public:
    virtual ~linearList(){};

    virtual bool emptyy() const = 0;
                //返回true,当且仅当线性表为空
    virtual int sizee() const = 0;
                //返回线性表的元素个数
    virtual T& get(int theIndex)const = 0;
                //返回索引为theIndex的元素
    virtual int indexOf(const T& theElement)const = 0;
                //返回元素theElement第一次出现的索引
    virtual void erasee(int theIndex) = 0;
                //删除索引为theIndex的元素
    virtual void insertt(int theIndex,const T& theElement) = 0;
                //把theElement插入线性表中索引为theIndex的位置上
    virtual void output(ostream& out)const = 0;
                //把线性表插入输出流out
};


#endif // LINEARLIST_H_INCLUDED

改变数组大小由oldLength到newLength

#ifndef CHANGELENGTH1D_H_INCLUDED
#define CHANGELENGTH1D_H_INCLUDED
template<class T>
void changeLength1D(T*& a,int oldLength,int newLength)
{
    if (newLength < 0)
        throw illegalParameterValue("new length must be >= 0");
    T* temp = new T[newLength]; //新数组
    int number = min(oldLength,newLength); //需要复制的元素个数
    copy(a, a+number,temp);
    delete[] a;//释放旧数组的内存空间
    a = temp;
}



#endif // CHANGELENGTH1D_H_INCLUDED

arrayList线性表实现

#ifndef ARRAYLIST_H_INCLUDED
#define ARRAYLIST_H_INCLUDED

#include<iostream>
#include<sstream>
#include<string>
#include<algorithm>
#include<iterator>
#include"myException.h"
#include"linearList.h"
#include"changeLength1D.h"
//C++中抽象类中包含没有实现代码的成员函数,这种函数称为纯虚函数
//纯虚函数用0作为初始值来说明
//具体类是没有虚函数的类,只有具体类才可以实例化
//只能对具体类建立实例或对象,不过可以建立抽象类的对象指针

//数组存储有多种方法
//location(i)=i、location(i)=arrayLength-i-1
template<class T>
class arrayList : public linearList<T>
{
public:
    //构造函数、复制构造函数、析构函数
    arrayList(int initialCapacity = 10);
    arrayList(const arrayList<T>&);
    ~arrayList()
    {
        delete [] element;
    }
    //ADT 方法
    bool emptyy() const
    {
        return listSize == 0;
    }
    int sizee ()const
    {
        return listSize;
    }
    T& get(int theIndex)const;
    int indexOf(const T& theElement)const;
    void erasee(int theIndex);
    void insertt(int theIndex,const T& theElement);
    void output(ostream& out)const;

    //其他方法
    int capacity()const
    {
        return arrayLength;
    }
    //iterator 为arrayList的内部类
    class iterator;
    iterator begin(){return iterator(element);}
    iterator end(){return iterator(element + listSize);}
    class iterator
    {
    public:
        //用C++的typedef语句实现双向迭代器
        typedef bidirectional_iterator_tag iterator_category;
        typedef T value_type;
        typedef ptrdiff_t difference_type;
        typedef T* pointer;
        typedef T& reference;

        //构造函数
        iterator(T* thePosition = 0)
        {
            position = thePosition;
        }

        //解引用操作符
        T& operator*()const
        {
            return *position;
        }
        T* operator->()const
        {
            return &*position;
        }

        iterator& operator++()
        {
            ++position;
            return *this;
        }
        iterator operator++(int)
        {
            iterator old = *this;
            ++position;
            return old;
        }
        iterator& operator--()
        {
            --position;
            return *this;
        }
        iterator operator--(int)
        {
            iterator old = *this;
            --position;
            return old;
        }
        bool operator != (const iterator right)const
        {
            return position != right.position;
        }
        bool operator == (const iterator right)const
        {
            return position == right.position;
        }
    protected:
        T* position;
    };
protected:
    void checkIndex(int theIndex)const;
    //若索引theIndex无效则抛出异常
    T* element;      //存储线性表元素的一维数组
    int arrayLength; //一维数组的容量
    int listSize;    //线性表的元素个数
};

template<class T>
arrayList<T>::arrayList(int initialCapacity)
{
    //构造函数
    if (initialCapacity < 1)
    {
        ostringstream s;
        s << "Initial capacity = "<< initialCapacity <<"Must be > 0";
        throw illegalParameterValue(s.str());
    }
    arrayLength = initialCapacity;
    element = new T[arrayLength];
    listSize = 0;
}

template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList)
{
    arrayLength = theList.arrayLength;
    listSize = theList.listSize;
    element = new T[arrayLength];
    //copy用来复制任何具有迭代器的元素
    copy(theList.element,theList.element +listSize,element);
}

template<class T>
void arrayList<T>::checkIndex(int theIndex)const
{
    if(theIndex < 0||theIndex >= listSize)
    {
        ostringstream s;
        s <<"index = "<< theIndex << "size = "<<listSize;
        throw illegalIndex(s.str());
    }
}

template<class T>
T& arrayList<T>::get(int theIndex)const
{
    checkIndex(theIndex);
    return element[theIndex];
}

template<class T>
int arrayList<T>::indexOf(const T& theElement)const
{
    //find返回值是目标元素的下标,找不到时返回值为迭代器结尾
    int theIndex = (int)(find(element,element + listSize,theElement)-element);

    if(theIndex == listSize)
        return -1;
    else return theIndex;
}

template<class T>
void arrayList<T>::erasee(int theIndex)
{
    //索引是否合法
    checkIndex(theIndex);
    //有效索引,移动其索引大于theIndex的元素
    copy(element + theIndex + 1,element + listSize,
         element + theIndex);

    //调用析构函数
    element[--listSize].~T();
}

template<class T>
void arrayList<T>::insertt(int theIndex,const T& theElement)
{
    if(theIndex < 0 || theIndex > listSize)
    {
        ostringstream s;
        s << "index = "<<theIndex<<"size = "<<listSize;
        throw illegalIndex(s.str());
    }
    if(listSize == arrayLength)
    {
        changeLength1D(element,arrayLength,2*arrayLength);
        arrayLength *= 2;
    }
    //copy_backward是从最右端的元素移动开始的
    copy_backward(element + theIndex,element + listSize,
                  element +listSize + 1);
    element[theIndex] = theElement;

    listSize++;
}

template<class T>
void arrayList<T>::output(ostream& out)const
{
    //ostream_iterator是输出流迭代器,可以用作打印控制台和输出文件的操作
    //底下这句话的意思就是把element和elemnet+listSize放到输出流中
    copy(element,element + listSize,ostream_iterator<T>(cout," "));
}

template<class T>
ostream& operator <<(ostream& out,const arrayList<T>& x)
{
    x.output(out);
    return out;
}

#endif // ARRAYLIST_H_INCLUDED

使用vector替代原arrayList中的数组

#ifndef VECTORLIST_H_INCLUDED
#define VECTORLIST_H_INCLUDED

#include<vector>
#include<sstream>
#include<algorithm>
using namespace std;
template<class T>
class vectorList : public linearList<T>
{
public:
    //构造函数、复制构造函数、析构函数
    vectorList(int initialCapacity = 10);
    vectorList(const vectorList<T>&);
    ~vectorList(){delete element;}

    //ADT方法
    bool emptyy()const{return element->emptyy();}
    int sizee()const{return (int)element->sizee();}
    T& get(int theIndex)const;
    int indexOf(const T& theElement)const;
    void erasee(int theIndex);
    void insertt(int theIndex,const T& theElement);
    void output(ostream& out)const;

    //增加的方法
    int capacity()const{return (int) element->capacity();}

    //线性表起始位置和终止位置的迭代器
    typedef typename vector<T>::iterator iterator;
    iterator begin(){return element->begin();}
    iterator end(){return element->end();}

protected:
    void checkIndex(int theIndex) const;
    vector<T>* element;
};

template<class T>
vectorList<T>::vectorList(int initialCapacity){
    if(initialCapacity < 1)
    {
        ostringstream s;
        s << "Initial capacity = "<<initialCapacity<<"Must be > 0";
        throw illegalParameterValue(s.str());
    }
    element = new vector<T>;
            //创建容量为0的空向量
    element->reverse(initialCapacity);
            //vector容量从0增加到initialCapacity
}
template<class T>
vectorList<T>::vectorList(const vectorList<T>& theList)
{//复制构造函数
    element = new vector<T>(*theList.element);
}
template<class T>
void vectorList<T>::erasee(int theIndex)
{
    checkIndex(theIndex);
    element->erasee(begin()+theIndex);
}
template<class T>
void vectorList<T>::insertt(int theIndex,const T& theElement)
{//在索引为theIndex出插入元素theElement
    if(theIndex < 0 || theIndex > sizee())
    {
        ostringstream s;
        s << "index = "<<theIndex<<" size = "<<sizee();
        throw illegalIndex(s.str());
    }
    element->insert(element->begin()+theIndex,theElement);

}
#endif // VECTORLIST_H_INCLUDED

总结:

  1. 对于一个类中只要包含了virtual方法,那么这个类就是抽象类,只能对具体类建立实例或对象,不过可以建立抽象类的对象指针;
  2. 继承抽象类必须实现其中的所有方法;
  3. 内部类,直接在class其中嵌套即可;
  4. copy方法复制任何具有迭代器的对象的元素;
  5. everse方法在<algorithm>中定义
    用以下方法将线性表y的元素逆置
reverse(y.begin(),y.end())
  1. 利用STL<numeric>的accumulate方法,对线性表y的元素求和
int sum = accumulate(y.begin(),y.end(),0);
  1. 继承某个类时使用的是如下,模板函数class T即泛型 ,就是要放到arrayList中的类型
class arrayList : public linearList<T>
{
};
  1. malloc和new的区别
  • 属性:new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
  • 内存区域:new操作符从自由存储区(free store)上为对象动态分配内存空间。自由存储是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。malloc函数从堆上动态分配内存,使用free释放已分配的对应内存。
  • 返回类型:返回类型安全性不同new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型
  • 分配失败:内存分配失败时的返回值不同new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL。malloc分配内存失败时返回NULL
  • 参数:是否需要指定内存大小不同使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。malloc则需要显式地指出所需内存的尺寸。
  • 重载:C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
  • 自定义类型: new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值