IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C++ - list简单实现 -> 正文阅读

[数据结构与算法]C++ - list简单实现

目录

一、整体框架

二、节点类

三、迭代器类

四、list类

1.构造与析构

? ?1.1?普通构造? ? ?? ?

1.2迭代器区间构造

1.3拷贝构造与赋值

1.4析构

2.迭代器指针、头尾数据

3.容量

4.插入和删除


一、整体框架

? ? ? ? 总共可分为节点类,迭代器类和list类三大块。

    // List的节点类
    template<class T>
    struct ListNode
    {
        ListNode(const T& val = T());
        ListNode<T>* _pPre;
        ListNode<T>* _pNext;
        T _val;
    };

    //List的迭代器类
    template<class T, class Ref, class Ptr>
    class ListIterator
    {
        typedef ListNode<T>* PNode;
        typedef ListIterator<T, Ref, Ptr> Self;
    public:
        ListIterator(PNode pNode = nullptr);
        ListIterator(const Self& l);
        T& operator*();
        T* operator->();
        Self& operator++();
        Self operator++(int);
        Self& operator--();
        Self& operator--(int);
        bool operator!=(const Self& l);
        bool operator==(const Self& l);
    private:
        PNode _pNode;
    };

    //list类
    template<class T>
    class list
    {
        typedef ListNode<T> Node;
        typedef Node* PNode;
    public:
        typedef ListIterator<T, T&, T*> iterator;
        typedef ListIterator<T, const T&, const T&> const_iterator;
    public:
        // List的构造
        list();
        list(int n, const T& value = T());
        template <class Iterator>
        list(Iterator first, Iterator last);
        list(const list<T>& l);
        list<T>& operator=(const list<T> l);
        ~list();
        // List Iterator
        iterator begin();
        iterator end();
        const_iterator begin();
        const_iterator end();
        // List Capacity
        size_t size()const;
        bool empty()const;
        // List Access
        T& front();
        const T& front()const;
        T& back();
        const T& back()const;
        // List Modify
        void push_back(const T& val) { insert(begin(), val); }
        void pop_back() { erase(--end()); }
        void push_front(const T& val) { insert(begin(), val); }
        void pop_front() { erase(begin()); }
        // 在pos位置前插入值为val的节点
        iterator insert(iterator pos, const T& val);
        // 删除pos位置的节点,返回该节点的下一个位置
        iterator erase(iterator pos);
        void clear();
        void swap(List<T>& l);
    private:
        void CreateHead();
        PNode _pHead;
    };

二、节点类

? ? ? ? list实现为双向循环链表。

    // List的节点类
    template<class T>
    struct ListNode
    {
        ListNode(const T& val = T())
            :_pPre(nullptr)
            ,_pNext(nullptr)
            ,_val(val)
        {}
        ListNode<T>* _pPre;
        ListNode<T>* _pNext;
        T _val;
    };

三、迭代器类

? ? ? ? 由于list中存储的地址不是连续的,我们不能使用原生指针来作迭代器。将节点指针放在迭代器类中,通过重载++,--,*等运算符,来实现迭代器。

? ? ? ? 模板参数Ref,使得传入const迭代器时,操作符*重载的返回值为const T&,实现只读不能写的功能。模板参数Ptr设置的原因也是如上,同时假设有迭代器it,要访问数据按操作符->重载使用应该是it->->_val,这样有两个箭头可读性太差了,编译器会优化成一个箭头,既it->_val。

    template<class T, class Ref, class Ptr>
    class ListIterator
    {
        typedef ListNode<T>* PNode;
        typedef ListIterator<T, Ref, Ptr> Self;
    public:
        ListIterator(PNode pNode = nullptr)
            :_pNode(pNode)
        {}
        ListIterator(const Self& l)
            :_pNode(l._pNode)
        {}
        Ref operator*()
        {
            return _pNode->_val;
        }
        Ptr operator->()
        {
            return &_pNode->_val;
        }
        Self& operator++()
        {
            _pNode = _pNode->_pNext;
            return *this;
        }
        Self operator++(int)
        {
            Self temp(*this);
            _pNode = _pNode->_pNext;
            return temp;
        }
        Self& operator--()
        {
            _pNode = _pNode->_pPre;
            return *this;
        }
        Self& operator--(int)
        {
            Self temp(*this);
            _pNode = _pNode->_pPre;
            return temp;
        }
        bool operator!=(const Self& l)
        {
            return _pNode != l._pNode;
        }
        bool operator==(const Self& l)
        {
            return _pNode == l._pNode;
        }
    private:
        PNode _pNode;
    };

四、list类

1.构造与析构

? ? ? ? 先封装一个头节点创建函数。

        void CreateHead()
        {
            _pHead = new Node();
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
        }

? ?1.1?普通构造? ? ?? ?

????????无参构造只需要创建一个头节点即可

? ? ? ? 利用push_back函数复用完成n个节点的初始化构造

        list()
        {
            CreateHead();
        }
        list(int n, const T& value = T())
        {
            CreateHead();
            while (n--)
            {
                push_back(value);
            }
        }

1.2迭代器区间构造

? ? ? ? 同样使用push_back函数,遍历迭代器区间进行构造。

        template <class Iterator>
        list(Iterator first, Iterator last)
        {
            CreateHead();
            while (first!=last)
            {
                push_back(*first);
                ++first;
            }
        }

1.3拷贝构造与赋值

? ? ? ? 复用迭代器区间构造,交换头节点指针。

        list(const list<T>& l)
        {
            list<T> temp(l.begin(), l.end());
            CreateHead();
            std::swap(_pHead, temp._pHead);
        }
        list<T>& operator=(const list<T> l)
        {
            CreateHead();
            std::swap(_pHead, l._pHead);
            return *this;
        }

1.4析构

? ? ? ? 复用clear函数再释放头节点指针。

        ~list()
        {
            clear();
            delete _pHead;
            _pHead = nullptr;
        }

2.迭代器指针、头尾数据

        // List Iterator
        iterator begin()
        {
            return iterator(_pHead->_pNext);
        }
        iterator end()
        {
            return iterator(_pHead);
        }
        const_iterator begin() const
        {
            return const_iterator(_pHead->_pNext);
        }
        const_iterator end() const
        {
            return const_iterator(_pHead);
        }
        // List Access
        T& front()
        {
            return *begin();
        }
        const T& front() const
        {
            return *begin();
        }
        T& back()
        {
            return *(--end());
        }
        const T& back() const
        {
            return *(--end());
        }

3.容量

        // List Capacity
        size_t size() const
        {
            size_t count = 0;
            iterator it = begin();
            while (it != end())
            {
                count++;
                it++;
            }
            return count;
        }
        bool empty() const
        {
            return _pHead == _pHead->_pNext;
        }

4.插入和删除

? ? ? ? 通过链表断开再链接完成插入和删除,其他的尾删和尾插等函数都可以复用插入和删除即可。

        // List Modify
        void push_back(const T& val) 
        { 
            insert(end(), val); 
        }
        void pop_back() 
        {
            erase(--end()); 
        }
        void push_front(const T& val) 
        {
            insert(begin(), val); 
        }
        void pop_front() 
        { 
            erase(begin()); 
        }
        // 在pos位置前插入值为val的节点
        iterator insert(iterator pos, const T& val)
        {
            PNode cur = pos._pNode;
            PNode prev = cur->_pPre;
            PNode newNode = new Node(val);
            prev->_pNext = newNode;
            newNode->_pNext = cur;
            cur->_pPre = newNode;
            newNode->_pPre = prev;
            return iterator(newNode);
        }
        // 删除pos位置的节点,返回该节点的下一个位置
        iterator erase(iterator pos)
        {
            PNode cur = pos._pNode;
            PNode prev = cur->_pPre;
            PNode next = cur->_pNext;
            delete cur;
            prev->_pNext = next;
            next->_pPre = prev;
            return iterator(next);
        }
        void clear()
        {
            iterator it = begin();
            while (it != end())
            {
                erase(it++);
            }
        }
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-17 22:25:52  更:2022-03-17 22:27:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:49:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码