模板实现顺序表+双向链表

用模板写链表主要还是为了实现代码的类型通用性,用模板写函数或类都与是类型无关的,因此,STL中都是用模板来实现容器,下面我们来介绍用模板实现顺序表和带头结点的双向循环链表。 以下代码将实现顺序表和链表的增、删、查、改、判空等常用接口以做练习。

顺序表


#pragma once

template<class T>
class SeqList
{
public:
    SeqList()
        :_a(NULL)
        , _size(0)
        , _capacity(0)
    {};

    SeqList(const SeqList<T>&s)//构造
    {
        _a = new T[s.size];
        for (size_t i = 0; i < s.size; ++i){
            _a[i] = s._a[i];
        }
        _size = s.size;
        _capacity = s.size;
    }

    SeqList<T>& operator = (SeqList<T> S) {//赋值运算符重载
        swap(_a, s._a);
        swap(_size, s._size);
        swap(capacity, s._capacity);

        return *this; 
    }
//析构
    ~SeqList(){
        if (_a){
            delete[] _a;
        }
    }

    void PushBack(const T& x)
    {
        CheckCapacity();
        _a[_size++] = x;//operatpr = 
    }

    void PopBack() {
        assert(_size > 0);
        --_size;
    }


    size_t GetSize() {
        return _size;
    }

    bool IsEmpty()
    {
        return _size == 0;
    }

    T& GetBackElement()
    {
        assert(_size > 0);
        return _a[size - 1];
    }

    //void Insert(size_t pos, const T& x);
    //void Erase(size_t pos);
    //size_t find(const T& x);


    void CheckCapacity()
    {
        if (_size == _capacity)
        {
            size_t newSize = _capacity ? _capacity * 2 : 3;//如果_capacity存在扩容2倍,置容量为3.
            T* tmp = new T[newSize];//临时新顺序表

            for (size_t i = 0; i < _size; ++i)//逐个拷贝至临时tmp中暂时存放
            {
                tmp[i] = _a[i];
            }

            delete[] _a;//释放回收旧表
            _a = tmp;//将tmp存放节点们赋给
            _capacity = newSize;
            assert(_a);//确保拷贝成功 _a不为空
        }   
    }

    void print() {
        for (size_t i = 0; i < _size; i++)
        {
            cout << _a[i] << " "<<endl;
        }
        cout << endl;
    }
protected:
    T * _a;
    size_t _size;
    size_t _capacity;
};

带头结点的循环双向链表

#pragma once

template<typename T>
struct ListNode
{
    ListNode<T>* _next;
    ListNode<T>* _prev;
    T _data;

    ListNode(const T& x)
        :_next(NULL)
        ,_prev(NULL)
        ,_data(x)
    {}
};

// 带头结点的双向循环链表
template<class T>
class List
{
    typedef ListNode<T> Node; 
public:
    List()
    {
        _head = new Node(T());
        _head->_next = _head;
        _head->_prev = _head;
    }

    // l2(l1)
    List(const List<T>& l)
    {
        _head = new Node(T());
        _head->_next = _head;
        _head->_prev = _head;

        Node* cur = l._head->_next;
        while (cur != l._head)
        {
            this->PushBack(cur->_data);
            cur = cur->_next;
        }
    }

    List<T>& operator=(List<T> l)
    {
        swap(_head, l._head);
        return *this;
    }

    ~List()
    {
        Clear();
        delete _head;
        _head = NULL;
    }

    void Clear()
    {
         Node* cur = _head->_next;
         while (cur != _head)
         {
            /* Node* next = cur->_next;
             delete cur;
             cur = next;*/
             Node* del = cur;
             cur = cur->_next;
             delete del;
         }

         _head->_next = _head;
         _head->_prev = _head;
    }

    void PushBack(const T& x)
    {
        Insert(_head, x);
    }

    void PopBack()
    {
        Erase(_head->_prev);
    }

    void PopFront()
    {
        Erase(_head->_next);
    }

    void PushFront(const T& x)
    {
        Insert(_head->_next, x);
    }

    void Insert(Node* pos, const T& x)
    {
        assert(pos);

        Node* prev = pos->_prev;
        Node* tmp = new Node(x);
        // prev tmp pos

        prev->_next = tmp;
        tmp->_prev = prev;
        tmp->_next = pos;
        pos->_prev = tmp;
    }

    void Erase(Node* pos)
    {
        assert(pos && pos != _head);
        Node* prev = pos->_prev;
        Node* next = pos->_next;
        delete pos;
        prev->_next = next;
        next->_prev = prev;
    }

    void Print()
    {
        Node* cur = _head->_next;
        while (cur != _head)
        {
            cout<<cur->_data<<" ";
            cur = cur->_next;
        }
        cout<<endl;
    }

    T& Back()
    {
        assert(!Empty());

        return _head->_prev->_data; 
    }

    const T& Front()
    {
        assert(!Empty());

        return _head->_next->_data; 
    }

    inline bool Empty()
    {
        return _head->_next == _head;
    }

    size_t Size()
    {
        size_t size = 0;
        Node* cur = _head->_next;
        while (cur != _head)
        {
            ++size;
            cur = cur->_next;
        }

        return size;
    }

protected:
    Node* _head;
};

//void TestList1()
//{
//  List<int> l;
//  l.PushBack(1);
//  l.PushBack(2);
//  l.PushBack(3);
//  l.PushBack(4);
//
//  l.PopBack();
//  l.PopBack();
//  l.PopBack();
//  l.PopBack();
//  l.Print();
//}

void TestList2()
{
    List<int> l;
    l.PushBack(1);
    l.PushBack(2);
    l.PushBack(3);
    l.PushBack(4);

    List<int> l2(l);
    l2.Print();
}

测试顺序表,链表

#include<iostream>
#include<string>
#include<assert.h>
#include<windows.h>
#include "SeqList.h"
#include "List.h"
using namespace std;

void TestSeqList()
{
    //SeqList<int> s1;
    //s1.PushBack(1);
    //s1.PushBack(2);
    //s1.PushBack(3);
    //s1.PushBack(4);
    //s1.PushBack(5);
    //s1.print();

    SeqList<string>s2;
    s2.PushBack("Still");
    s2.PushBack("Still is pig!!");
    s2.PushBack("What a foolish Still!");
    s2.PushBack("Stillis a pig forever!");

    s2.print();
    //SeqList<string> s3(s2);
    //s3.print();
}

int main()
{
    TestSeqList();
    //TestList2();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象程序设计课程作业 1. 请创建一个数据类型为T的链表模板List,实现以下成员函数: 1) 默认构造函数List(),将该链表初始化为一个空链表(10分) 2) 拷贝构造函数List(const List& list),根据一个给定的链表构造当前链表(10分) 3) 析构函数~List(),释放链表中的所有节点(10分) 4) Push_back(T e)函数,往链表最末尾插入一个元素为e的节点(10分) 5) operator<<()友元函数,将链表的所有元素按顺序输出(10分) 6) operator=()函数实现两个链表的赋值操作(10分) 7) operator+()函数实现两个链表的连接,A=B+C(10分) 2. 请编写main函数,测试该类模板的正确性: 1) 用List模板定义一个List类型的模板类对象int_listB,从键盘读入m个整数,调用Push_back函数将这m个整数依次插入到该链表中;(4分) 2) 用List模板定义一个List类型的模板类对象int_listC,从键盘读入n个整数,调用Push_back函数将这n个整数依次插入到该链表中;(4分) 3) 用List模板定义一个List类型的模板类对象int_listA,调用List的成员函数实现A = B + C;(4分) 4) 用cout直接输出int_listA的所有元素(3分) 5) 用List模板定义List类型的模板类对象double_listA, double_listB, double_listC,重复上述操作。(15分) 3. 输入输出样例: 1) 输入样例 4 12 23 34 45 3 56 67 78 3 1.2 2.3 3.4 4 4.5 5.6 6.7 7.8 2) 输出样例 12 23 34 45 56 67 78 1.2 2.3 3.4 4.5 5.6 6.7 7.8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值