【C++】c++实现线性表、链表

c++实现动态顺序表如下

typedef int DataType;
class SeqList
{
public: 
    //类的基本成员函数定义/
    SeqList()                     //构造函数(在类内定义)
        :_elem(NULL)
        , _capacity(0)
        , _size(0)
    {}
    ~SeqList()                  //析构函数
    {
        if (_elem)
        {
            delete[] _elem;
            cout << "~SeqList()" << endl;
        }
    }
    SeqList(const SeqList& s)    //拷贝构造函数
        :_elem(new DataType[s._capacity])
        , _capacity(s._capacity)
        , _size(s._size)
    {
        memcpy(_elem, s._elem, _size*sizeof(DataType));
    }
    SeqList& operator= (const SeqList& s)  //赋值操作符重载
    {
        if (this != &s)  //防止自赋值
        {
            delete[] _elem;//释放原来空间
            _elem = new DataType[s._capacity];//分配新空间
            memcpy(_elem, s._elem, s._size*sizeof(DataType));
            _size = s._size;
            _capacity = s._capacity;
        }
        return *this;
    }
    //////////动态顺序表的基本操作实现///////////////
    void _CheckCapacity();         //在类外定义
    void _PrintSeqList();
    void _PushBack(DataType data);
    void _PopBack();
    size_t Find(DataType data);
    void Insert(size_t index,DataType data);
private:
    DataType* _elem;   //指向当前空间的指针
    size_t _capacity;     //当前空间容量大小
    size_t _size;          //但钱空间有效数据的个数
};

类外定义成员函数如下:

void SeqList::_CheckCapacity()         //检查容量
{
    if (_size == _capacity)
    {
        _capacity = _capacity * 2 + 5;//构造函数初始化时,_capacity为0
        DataType* ret = (DataType*)malloc(_capacity*sizeof(DataType));
        memcpy(ret, _elem, _size*sizeof(DataType));
        delete[] _elem;
        _elem = ret;
    }
}
void SeqList::_PrintSeqList()
{
    cout << "SeqList : ";
    size_t index = 0;
    for (; index < _size; index++)
    {
        cout << _elem[index] << " ";
    }
    cout << "NULL" << endl;
}
void SeqList::_PushBack(DataType data) //尾插数据
{
    _CheckCapacity();
    _elem[_size++] = data;
}
void SeqList::_PopBack()
{
    if (_size == 0)
    {
        cout << "SeqList Is Empty" << endl;
        return;
    }
    _size--;
}
size_t SeqList::Find(DataType data)    //查找数据,返回下标
{
    size_t index = 0;
    for (; index < _size; index++)
    {
        if (_elem[index] == data)
        {
            return index;
        }
    }
    return _size+1;
}
void SeqList::Insert(size_t index, DataType data) //在下标index处插入一个数据
{
    _CheckCapacity();
    if (index > _size)
    {
        cout << "Invaid index" << endl;
        return;
    }
    int i = _size-1;
    for (; i >=(int)index; i--)  //注意此处i不能定义为size_t,且index要强转成int型,否则会成死循环
    {                            //即使i一直减,但是无符号整型永远不会小于0,
        _elem[i+1] = _elem[i];
    }
    _elem[index] = data;
    _size++;
}
基本成员函数(如构造、拷贝构造、赋值操作符重载函数)还可以优化如下:
class SeqList
{
public:
    //类的基本成员函数定义/
    SeqList(DataType* elem, size_t capacity, size_t size)   //构造函数
    {
        if (elem == NULL)
        {
            _elem = NULL;
            _capacity = 0;
            _size = 0;
        }
        else
        {
            _elem = new DataType[capacity];
            memcpy(_elem, elem, size*sizeof(DataType));
            _capacity = capacity;
            _size = size;
        }
    }
    ~SeqList()                  //析构函数
    {
        if (_elem)
        {
            delete[] _elem;
            cout << "~SeqList()" << endl;
        }
    }
    void Swap(SeqList& s)
    {
        swap(_elem, s._elem);//自动调用系统实现的swap函数
        swap(_capacity, s._capacity);
        swap(_size, s._size);
    }
    SeqList(const SeqList& s)    //拷贝构造函数
        :_elem(NULL)
        , _capacity(0)
        , _size(0)
    {
        SeqList tmp(s._elem, s._capacity, s._size);//通过构造函数进行初始化
        Swap(tmp);  //将tmp与this的值交换,交换后this会指向原来tmp指向的空间
    }
    SeqList& operator= (const SeqList& s)  //赋值操作符重载
    {
        if (this != &s)  //防止自赋值
        {
            SeqList tmp(s._elem, s._capacity, s._size);
            Swap(tmp);
        }
        return *this;
    }
private:
    DataType* _elem;   //指向当前空间的指针
    size_t _capacity;     //当前空间容量大小
    size_t _size;          //但钱空间有效数据的个数
};
解析:

SeqList tmp(s._elem, s._capacity, s._size);
Swap(tmp);
若已经存在的两个对象s1、s2;执行 s1 = s2 操作,则先创建一个临时对象tmp,将s2的值拷贝给tmp,再将tmp和s1的值进行交换,最后出了作用域就会释放这个临时对象tmp。如下图:

这里写图片描述


c++实现链表如下

单向循环链表

先了解:
关键字struct和class是同一等级的,
唯一区别是struct定义的成员默认是公有的,而class默认的成员是私有的
typedef int DataType;
struct LinkNode
{
    LinkNode* _next;     //指向下一个节点的指针
    DataType _data;  //当前节点的数据
    LinkNode(const DataType data)    //构造函数
        :_next(NULL)
        ,_data(data)
    {}
};
class sList
{
public:
    sList()                        //构造函数
        :_head(NULL)
        ,_tail(NULL)
    {}
    sList(const sList& s)         //拷贝构造函数
        :_head(NULL)
        ,_tail(NULL)
    {
        if(s._head == NULL)
        {
            return;
        }
        LinkNode* begin = s._head;
        do
        {
            PushBack(begin->_data);  //this->PushBack(begin->_data);
            begin = begin->_next;
        } while (begin != s._head);
    }
    sList& operator= (const sList& s)   //赋值操作符重载
    {
        if (this != &s)
        {
            DistorysList();//先摧毁this指向的链表
            LinkNode* begin = s._head;
            do
            {
                PushBack(begin->_data);
                begin = begin->_next;
            } while (begin != s._head);
        }
        return *this;
    } 
    ~sList()                       //析构函数
    {
        Distory();
    }
    void DistorysList()            //撤销链表
    {
        while (_head)
        {
            PopBack();
        }
    }
    void PushBack(DataType data)    //尾插
    {
        if (_head == NULL)
        {
            _head = new LinkNode(data);
            _tail = _head;   //循环链表
        }
        else
        {
            _tail->_next = new LinkNode(data);
            _tail = _tail->_next;
            _tail->_next = _head;
        }
    }
    void PopBack()                  //尾删
    {
        if (_head == NULL)//空链表
        {
            return;
        }
        if (_head == _tail)//一个节点
        {
            delete _head;
            _head = NULL;
            _tail = NULL;
        }
        else               //多个节点
        {
            LinkNode* prev = _head;
            while (prev->_next != _tail)
            {
                prev = prev->_next;
            }
            delete _tail;
            _tail = prev;
            _tail->_next = _head;
        }
    }
    void PrintsList()                  //打印链表
    {
        cout << "sList->";
        if (_head != NULL)
        {
            LinkNode* begin = _head;
            do
            {
                cout << begin->_data << "->";
                begin = begin->_next;
            }while (begin != _head);
        }
        cout << "NULL" << endl;
    }
    void Reverse()               //逆置链表
    {
        if (_head == NULL || _head == _tail)
        {
            return;
        }
        LinkNode* begin = _head->_next;
        _head->_next = NULL;//摘下头节点
        _tail->_next = NULL;//解开循环
        _tail = _head;      //原来的头节点逆置后是尾节点
        while (begin)
        {
            LinkNode* ret = begin;
            begin = begin->_next;
            ret->_next = _head;
            _head = ret;
        }
        _tail->_next = _head;
    }
private: 
    LinkNode* _head;   //指向头节点的指针
    LinkNode* _tail;   //指向尾节点的指针
};

双向循环链表

typedef int DataType;
class DoubleNode
{
    friend class DoubleList;        //友元函数
public: 
    DoubleNode(DataType data)       //构造函数
        :_prev(NULL)
        , _next(NULL)
        , _data(data)
    {}
private:
    DoubleNode* _prev;
    DoubleNode* _next;
    DataType _data;
};
class DoubleList
{
public:
    DoubleList()               //构造函数
        :_head(NULL)
        , _tail(NULL)
    {}
    DoubleList(const DoubleList& d) //拷贝构造函数
        :_head(NULL)
        , _tail(NULL)
    {
        if (d._head == NULL)
        {
            return;
        }
        DoubleNode* begin = d._head;
        do
        {
            PushBack(begin->_data);
            begin = begin->_next;
        }while (begin != d._head);
    }
    DoubleList& operator= (const DoubleList& d)    //赋值操作符重载
    {
        if (this != &d)
        {
            Distory();
            DoubleNode* begin = d._head;
            do
            {
                PushBack(begin->_data);
                begin = begin->_next;
            } while (begin != d._head);
        }
        return *this;
    }
    ~DoubleList()                       //析构函数
    {
        Distory();
    }
    void Distory()                   //摧毁链表
    {
        while (_head)
        {
            PopFront();
        }
    }
    void PushBack(DataType data)     //尾插
    {
        if (_head == NULL)
        {
            _head = new DoubleNode(data);
            _tail = _head;
        }
        else
        {
            DoubleNode* ret = new DoubleNode(data);
            _tail->_next = ret;
            ret->_prev = _tail;
            _tail = ret;
            _tail->_next = _head;   //成环
        }
    }
    void PopFront()              //头删
    {
        if (_head == NULL)
        {
            cout << "DoubleList Is Empty" << endl;
        }
        else if (_head == _tail)
        {
            delete _head;
            _head = NULL;
            _tail = NULL;
        }
        else
        {
            DoubleNode* del = _head;
            _head = _head->_next;
            _head->_prev = NULL;
            _tail->_next = _head;//更新尾指针
            del->_next = NULL;
            delete del;
        }
    }
    void PrintDList()
    {
        cout << "DoubleList->";
        if (_head != NULL)
        {
            DoubleNode* begin = _head;
            do
            {
                cout << begin->_data << "->";
                begin = begin->_next;
            } while (begin != _head);
        }
        cout << "NULL" << endl;
    }
private:
    DoubleNode* _head;    //指向尾节点的指针
    DoubleNode* _tail;    //指向头节点的指针
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值