讨论stl链表

2024-06-26 1021阅读

讨论链表

  • list迭代器失效
  • list的模拟实现
    • 创建结点类
    • 链表迭代器
    • 完成实现代码
    • list与vector

      链表是一个序列容器,在任意位置都可以用常数时间插入或者删除,并且可以在两个方向进行迭代。

      讨论stl链表

      list迭代器失效

      迭代器失效指迭代器所指向的结点无效,即该结点被删除了。

      • list的底层结构是双向带头循环链表,因此向list中插入数据是不会造成迭代器失效。
      • 但删除数据时,指向删除结点的迭代器会失效,其他迭代器不会受影响。

        list的模拟实现

        创建结点类

        • 链表是由一个一个结点组成,结点中存放储存的元素已经指向下一个以及前一个的指针。
          template
          struct list_node {
              T _val;
              list_node *_prev;
              list_node *_next;
              list_node(const T &val = T())
                      : _val(val), _prev(nullptr), _next(nullptr) {}
          };
          

          链表迭代器

          • 链表的迭代器不同于顺序表。顺序表的迭代器可以直接返回头部和尾部指针的位置。++操作只需要移动相应字节数的指针即可完成。

            讨论stl链表

            • 链表迭代器++操作不能依靠简单的指针++完成,因为不是连续空间,因此需要封装一层结点结构,以_node = _node->next来达到++的效果。
              template
              struct __list_iterator {
                  typedef list_node node;
                  typedef __list_iterator self;
                  node *_node;
                  __list_iterator(node *node = nullptr)
                          : _node(node) {}
                  self &operator++() {
                      _node = _node->_next;
                      return *this;
                  }
                  self operator++(int) {
                      self tmp(*this);
                      _node = _node->next;
                      return tmp;
                  }
                  self &operator--() {
                      _node = _node->_prev;
                      return *this;
                  }
                  self operator--(int) {
                      self tmp(*this);
                      _node = _node->_prev;
                      return tmp;
                  }
                  Ref operator*() {
                      return _node->_val;
                  }
                  Ptr operator->() {
                      return &_node->_val;
                  }
                  bool operator!=(const self &s) {
                      return _node != s._node;
                  }
                  bool operator==(const self &s) {
                      return _node == s._node;
                  }
              };
              
              • 其中Ref和Ptr模板为传入引用或者指针对象区分const和非const的模板。

                完成实现代码

                namespace max {
                    template
                    struct list_node {
                        T _val;
                        list_node *_prev;
                        list_node *_next;
                        list_node(const T &val = T())
                                : _val(val), _prev(nullptr), _next(nullptr) {}
                    };
                    // 迭代器封装
                    template
                    struct __list_iterator {
                        typedef list_node node;
                        typedef __list_iterator self;
                        node *_node;
                        __list_iterator(node *node = nullptr)
                                : _node(node) {}
                        self &operator++() {
                            _node = _node->_next;
                            return *this;
                        }
                        self operator++(int) {
                            self tmp(*this);
                            _node = _node->next;
                            return tmp;
                        }
                        self &operator--() {
                            _node = _node->_prev;
                            return *this;
                        }
                        self operator--(int) {
                            self tmp(*this);
                            _node = _node->_prev;
                            return tmp;
                        }
                        Ref operator*() {
                            return _node->_val;
                        }
                        Ptr operator->() {
                            return &_node->_val;
                        }
                        bool operator!=(const self &s) {
                            return _node != s._node;
                        }
                        bool operator==(const self &s) {
                            return _node == s._node;
                        }
                    };
                    template
                    class list {
                        typedef list_node node;
                        typedef __list_iterator iterator;
                        typedef __list_iterator const_iterator;
                    public:
                        void empty_init() {
                            _head = new node();
                            _head->_next = _head;
                            _head->_prev = _head;
                            _size = 0;
                        }
                        list() {
                            empty_init();
                        }
                        list(int n, const T &val = T()) {
                            empty_init();
                            for (int i = 0; i _prev;
                            end->_next = newNode;
                            newNode->_prev = end;
                            newNode->_next = _head;
                            _head->_prev = newNode;
                            ++_size;
                        }
                        void push_front(const T &val) {
                            node *newNode = new node(val);
                            node *next = _head->_next;
                            newNode->_next = next;
                            next->_prev = newNode;
                            _head->_next = newNode;
                            newNode->_prev = _head;
                        }
                        void pop_back() {
                            assert(_head->_next != _head);
                            node *del = _head->_prev;
                            _head->_prev = del->_prev;
                            del->_prev->_next = _head;
                            delete del;
                            del = nullptr;
                            --_size;
                        }
                        void pop_front() {
                            assert(_head->_next != _head);
                            node *del = _head->_next;
                            _head->_next = del->_next;
                            del->_next->_prev = _head;
                            delete del;
                            del = nullptr;
                            --_size;
                        }
                        iterator begin() {
                            return iterator(_head->_next);
                        }
                        iterator end() {
                            return iterator(_head);
                        }
                        const_iterator begin() const {
                            return const_iterator(_head->_next);
                        }
                        const_iterator end() const {
                            return const_iterator(_head);
                        }
                        iterator insert(iterator pos, const T &val) {
                            node *newNode = new node(val);
                            node *prev = pos._node->_prev;
                            prev->next = newNode;
                            newNode->_prev = prev;
                            newNode->_next = pos._node;
                            pos._node->_prev = newNode;
                            ++_size;
                            return iterator(newNode);
                        }
                        iterator erase(iterator pos) {
                            assert(_head != _head->_next);
                            node *cur = pos._node;
                            node *next = cur->_next;
                            node *prev = cur->_prev;
                            prev->_next = next;
                            next->_prev = prev;
                            delete cur;
                            cur = nullptr;
                            --_size;
                            return iterator(next);
                        }
                        void clear() {
                            iterator it = begin();
                            while (it != end()) {
                                it = erase(it);
                                --_size;
                            }
                        }
                        size_t size() const {
                            return _size;
                        }
                    private:
                        node *_head;
                        size_t _size;
                    };
                }
                

                list与vector

                • 因vector和list底层结构不同,因此在使用场景上存在一定差异。
                  vectorlist
                  底层结构动态顺序表,一段连续的空间。带头双向循环链表
                  随机访问支持随机访问,效率为O(1)。不支持随机访问,访问某个元素的效率为O(N)。
                  插入和删除尾插和尾删时效率是O(1)。除此之外插入删除的效率都很低,因为需要移动数据,若插入大量数据还涉及到扩容,异地扩容需要拷贝元素和释放旧空间,效率很低。任意位置插入和删除数据效率为O(1)。不需要移动数据。
                  空间利用率底层为连续空间,不容易产生内存碎片,利用率高,缓存利用率高。底层为动态开辟的小结点,容易造成内存碎片,空间利用率低,缓存利用率低。
                  迭代器原生态指针。对原生态指针进行封装。
                  迭代器失效插入元素时可能会造成迭代器失效,因为可能会异地扩容。删除元素时当前迭代器会失效。插入元素时不会造成迭代器失效,删除元素时会造成当前迭代器失效,其他迭代器不受影响。
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]