数据结构cpp实现——线性表

一、线性表定义

        标准定义:线性表的数据集合为{a1,a2,…,an},假设每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。

学习,编程,计算机,数据结构
            个人理解:线性表的定义并没有规定存储结构,可以在空间上连续,也可以通过指针连串。


线性表顺序表示

学习,编程,计算机,数据结构
    顺序表基本概念:用一组地址连续的存储单元依次存储线性表的数据元素,这种存储结构的线性表称为顺序表。    本质上仍然是数组的存储形式,但是存储数据的类型可以扩展为多种形式。

    顺序表的类模版实现

#include <cstdlib>

#include <iostream>

#include "assert.h"

template<class T>

class SeqList {

private:

    int length;//顺序表当前所含有的元素个数

    int maxLength;//顺序表最大容量,在构造函数中由用户给出的数据生成

    T *elems= nullptr;//元素存储空间首地址,默认为nullptr,防止出错

public:

    SeqList(){};

    SeqList(T *array, int SizeOfArray, int size=10);//构造函数,第一个参数为传入的初始化数组,第二个参数为传入数组大小,第三个参数为容器最大容量,设置默认参数为10

    ~SeqList();//析构函数

    int GetLength() const;//返回顺序表当前长度

    bool IsEmpty() const;//顺序表为空返回true,非空返回false

    void clear(); //清空顺序表

    void traverse() const;// 遍历打印顺序表

    int LocateElem(const T &e) const; //定位元素e在顺序表中的位置

    bool GetElem(int i, T &e) const; //取第i个元素并赋值给e并返回true,若失败函数整体返回false

    bool SetElem(int i, const T &e); //用传入的e替换第i个元素,替换成功返回true,替换失败返回false

    bool DeleteElem(int i, T &e);//删除第i个元素,并把删除的元素赋值给e

    bool InsertElem(const T &e);//在表尾插入元素

    bool InsertElem(int i, const T &e);//在第i个位置插入元素

    SeqList(const SeqList<T> &origin);//复制构造函数

    SeqList<T> &operator = (const SeqList<T> &origin);//赋值语句重载

};


template<class T>

SeqList<T>::SeqList(T *array, int SizeOfArray, int size) {

    if(size<SizeOfArray)

        exit(1);//如果分配的最大内存空间小于初始化数组的大小,则退出程序

    length=SizeOfArray;//当前顺序表长度为初始化数组大小

    maxLength=size;//最大长度为size

    elems=new T[size];//分配内存空间

    assert(elems);//分配内存空间失败则报错并终止程序

    for(int i=0;i<SizeOfArray;i++)

        elems[i]=array[i];

}


template<class T>

SeqList<T>::~SeqList() {

    delete [] elems;

}


template<class T>

int SeqList<T>::GetLength() const {

    return length;

}


template<class T>

bool SeqList<T>::IsEmpty() const {

    return length==0;

}


template<class T>

void SeqList<T>::clear() {

    length=0;//这里我们只清除了length,并没有实际释放分配的内存

}


template<class T>

void SeqList<T>::traverse() const {

    for(int i=0;i < length; i++)

        std::cout<<elems[i]<<" "<<std::endl;

}


template<class T>

int SeqList<T>::LocateElem(const T &e) const {

    int i=0;

    while(i<length&&elems[i] !=e)

        i++;

    return i<length ? i+1:0;//i小于length,说明找到了对应元素,返回i+1,否则返回0

}


template<class T>

bool SeqList<T>::GetElem(int i, T &e) const {

    if(i>length||i<1)

        return false;//定位位置大于顺序表长度或给出非法值,返回false

    else

    {

        e=elems[i-1];

        return true;

    }

}


template<class T>

bool SeqList<T>::SetElem(int i, const T &e) {

    if(i>length||i<1)

        return false;//位置错误,返回false

    else

    {

        elems[i-1]=e;

        return true;

    }

}


template<class T>

bool SeqList<T>::DeleteElem(int i, T &e) {

    if(i>length||i<1)

        return false;//位置错误,返回false

    else

    {

        e=elems[i-1];

        for(int j=i;j<length;j++)

            elems[j-1]=elems[j];//删除后,元素依次从后往前移动

        length--;

        return true;

    }

}


template<class T>

bool SeqList<T>::InsertElem(const T &e) {

    if(length==maxLength)

        return false;//表尾插入元素,若超过最大存储空间,返回false

    else

    {

        elems[length]=e;

        length++;

        return true;

    }

}


template<class T>

bool SeqList<T>::InsertElem(int i, const T &e) {

    if(length==maxLength)

        return false;

    else if(i<1||i>length+1)

        return false;

    else

    {

        for(int j=length;j>=i;j--)

            elems[j]=elems[j-1];//元素从前往后移动,给第i个元素腾空间

        elems[i-1]=e;

        length++;

        return true;

    }

}


template<class T>

SeqList<T>::SeqList(const SeqList<T> &origin) {

    if(this->elems!= nullptr)

        delete [] elems;//如果元素指针被赋过值,则将其清空

    elems=new T[origin.maxLength];

    for(int i=0;i<origin.GetLength();i++)

        elems[i]=origin.elems[i];//元素逐个赋值

    this->length=origin.GetLength();//当前顺序表长度复制

    this->maxLength=origin.maxLength;//当前最大长度复制

}


template<class T>

SeqList<T> &SeqList<T>::operator=(const SeqList<T> &origin) {

    //=的重载其实和复制构造函数一样

    if(this->elems!= nullptr)

        delete [] elems;//如果元素指针被赋过值,则将其清空

    this->elems=new T[origin.maxLength];

    for(int i=0;i<origin.GetLength();i++)

        this->elems[i]=origin.elems[i];//元素逐个赋值

    this->length=origin.GetLength();//当前顺序表长度复制

    this->maxLength=origin.maxLength;//当前最大长度复制

    return *this;

}上面的代码因为泛化编程的原因,方法声明和实现都放在h文件里面,复制可以直接用。


顺序表是最简单的数据结构,其实就是一个特殊的数组,因为模版的原因可以存储更广泛的的类型数据。

发布评论
全部评论(20)
用户头像

帅啊,计算机学生路过 [s-7]

用户头像

[s-6]

用户头像
Hannah#375471

[s-7]

用户头像
5077#375469

[s-1]