• 【STL***list容器一】


    目录

    __list_node链表结构

    __list_iterator结构

    __list_iterator构造函数

    __list_iterator操作符重载

    list结构

    list构造与析构

    属性获取


    vector容器在涉及高频率插入删除时效率太低了

    list是用链表进行实现的,链表删除插入时间复杂度为O(1),效率相当高,不过随机访问就会变成O(n).list在插入和删除操作后,迭代器不会失效

    __list_node链表结构

    1. template <class T> struct __list_node
    2. {
    3. // 前后指针
    4. typedef void* void_pointer;
    5. void_pointer next;
    6. void_pointer prev;
    7. // 属性
    8. T data;
    9. };

    __list_iterator结构

    1. template<class T, class Ref, class Ptr> struct __list_iterator
    2. {
    3. typedef __list_iterator iterator; // 迭代器
    4. typedef __list_iteratorconst T&, const T*> const_iterator;
    5. typedef __list_iterator self;
    6. // 迭代器是bidirectional_iterator_tag类型
    7. typedef bidirectional_iterator_tag iterator_category;
    8. typedef T value_type;
    9. typedef Ptr pointer;
    10. typedef Ref reference;
    11. typedef size_t size_type;
    12. typedef ptrdiff_t difference_type;
    13. ...
    14. };

    __list_iterator构造函数

    1. template<class T, class Ref, class Ptr> struct __list_iterator
    2. {
    3. ...
    4. // 定义节点指针
    5. typedef __list_node* link_type;
    6. link_type node;
    7. // 构造函数
    8. __list_iterator(link_type x) : node(x) {}
    9. __list_iterator() {}
    10. __list_iterator(const iterator& x) : node(x.node) {}
    11. ...
    12. };

    __list_iterator操作符重载

    1. template<class T, class Ref, class Ptr> struct __list_iterator
    2. {
    3. ...
    4. // 重载
    5. bool operator==(const self& x) const { return node == x.node; }
    6. bool operator!=(const self& x) const { return node != x.node; }
    7. // 对*和->操作符进行重载
    8. reference operator*() const { return (*node).data; }
    9. #ifndef __SGI_STL_NO_ARROW_OPERATOR
    10. pointer operator->() const { return &(operator*()); }
    11. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
    12. // ++和--是直接操作的指针指向next还是prev, 因为list是一个双向链表
    13. self& operator++()
    14. {
    15. node = (link_type)((*node).next);
    16. return *this;
    17. }
    18. self operator++(int)
    19. {
    20. self tmp = *this;
    21. ++*this;
    22. return tmp;
    23. }
    24. self& operator--()
    25. {
    26. node = (link_type)((*node).prev);
    27. return *this;
    28. }
    29. self operator--(int)
    30. {
    31. self tmp = *this;
    32. --*this;
    33. return tmp;
    34. }
    35. };

    list结构

    1. template <class T, class Alloc = alloc>
    2. class list
    3. {
    4. protected:
    5. typedef void* void_pointer;
    6. typedef __list_node list_node; // 节点
    7. typedef simple_alloc list_node_allocator; // 空间配置器
    8. public:
    9. // 定义嵌套类型
    10. typedef T value_type;
    11. typedef value_type* pointer;
    12. typedef const value_type* const_pointer;
    13. typedef value_type& reference;
    14. typedef const value_type& const_reference;
    15. typedef list_node* link_type;
    16. typedef size_t size_type;
    17. typedef ptrdiff_t difference_type;
    18. protected:
    19. // 定义一个节点, 这里节点并不是一个指针.
    20. link_type node;
    21. public:
    22. // 定义迭代器
    23. typedef __list_iterator iterator;
    24. typedef __list_iteratorconst T&, const T*> const_iterator;
    25. ...
    26. };

    list构造与析构

    前期准备

    1. template <class T, class Alloc = alloc>
    2. class list
    3. {
    4. ...
    5. protected:
    6. // 分配一个元素大小的空间, 返回分配的地址
    7. link_type get_node() { return list_node_allocator::allocate(); }
    8. // 释放一个元素大小的内存
    9. void put_node(link_type p) { list_node_allocator::deallocate(p); }
    10. // 分配一个元素大小的空间并调用构造初始化内存
    11. link_type create_node(const T& x)
    12. {
    13. link_type p = get_node();
    14. __STL_TRY {
    15. construct(&p->data, x);
    16. }
    17. __STL_UNWIND(put_node(p));
    18. return p;
    19. }
    20. // 调用析构并释放一个元素大小的空间
    21. void destroy_node(link_type p) {
    22. destroy(&p->data);
    23. put_node(p);
    24. }
    25. // 对节点初始化
    26. void empty_initialize()
    27. {
    28. node = get_node();
    29. node->next = node;
    30. node->prev = node;
    31. }
    32. ...
    33. };

    构造函数

    1. 多个重载, 以实现直接构造n个节点并初始化一个值, 支持传入迭代器进行范围初始化, 也支持接受一个list参数, 同样进行范围初始化.
    2. 每个构造函数都会创造一个空的node节点, 为了保证我们在执行任何操作都不会修改迭代器
    1. template <class T, class Alloc = alloc>
    2. class list
    3. {
    4. ...
    5. protected:
    6. // 构造函数
    7. list() { empty_initialize(); } // 默认构造函数, 分配一个空的node节点
    8. // 都调用同一个函数进行初始化
    9. list(size_type n, const T& value) { fill_initialize(n, value); }
    10. list(int n, const T& value) { fill_initialize(n, value); }
    11. list(long n, const T& value) { fill_initialize(n, value); }
    12. // 分配n个节点
    13. explicit list(size_type n) { fill_initialize(n, T()); }
    14. #ifdef __STL_MEMBER_TEMPLATES
    15. // 接受两个迭代器进行范围的初始化
    16. template <class InputIterator>
    17. list(InputIterator first, InputIterator last) {
    18. range_initialize(first, last);
    19. }
    20. #else /* __STL_MEMBER_TEMPLATES */
    21. // 接受两个迭代器进行范围的初始化
    22. list(const T* first, const T* last) { range_initialize(first, last); }
    23. list(const_iterator first, const_iterator last) {
    24. range_initialize(first, last);
    25. }
    26. #endif /* __STL_MEMBER_TEMPLATES */
    27. // 接受一个list参数, 进行拷贝
    28. list(const list& x) {
    29. range_initialize(x.begin(), x.end());
    30. }
    31. list& operator=(const list& x);
    32. ...
    33. };

     

    1. void fill_initialize(size_type n, const T& value) {
    2. empty_initialize();
    3. __STL_TRY {
    4. insert(begin(), n, value);
    5. }
    6. __STL_UNWIND(clear(); put_node(node));
    7. }

    析构函数

    1. ~list() {
    2. // 删除初空节点以外的所有节点
    3. clear();
    4. // 删除空节点
    5. put_node(node);
    6. }

    属性获取

    list中的迭代器一般不会被修改, 因为node节点始终指向的一个空节点同时list是一个循环的链表, 空节点正好在头和尾的中间, 所以node.next就是指向头的指针, node.prev就是指向结束的指针, end返回的是最后一个数据的后一个地址也就是node

    1. template <class T, class Alloc = alloc>
    2. class list
    3. {
    4. ...
    5. public:
    6. iterator begin() { return (link_type)((*node).next); } // 返回指向头的指针
    7. const_iterator begin() const { return (link_type)((*node).next); }
    8. iterator end() { return node; } // 返回最后一个元素的后一个的地址
    9. const_iterator end() const { return node; }
    10. // 这里是为旋转做准备, rbegin返回最后一个地址, rend返回第一个地址. 我们放在配接器里面分析
    11. reverse_iterator rbegin() { return reverse_iterator(end()); }
    12. const_reverse_iterator rbegin() const {
    13. return const_reverse_iterator(end());
    14. }
    15. reverse_iterator rend() { return reverse_iterator(begin()); }
    16. const_reverse_iterator rend() const {
    17. return const_reverse_iterator(begin());
    18. }
    19. // 判断是否为空链表, 这是判断只有一个空node来表示链表为空.
    20. bool empty() const { return node->next == node; }
    21. // 因为这个链表, 地址并不连续, 所以要自己迭代计算链表的长度.
    22. size_type size() const {
    23. size_type result = 0;
    24. distance(begin(), end(), result);
    25. return result;
    26. }
    27. size_type max_size() const { return size_type(-1); }
    28. // 返回第一个元素的值
    29. reference front() { return *begin(); }
    30. const_reference front() const { return *begin(); }
    31. // 返回最后一个元素的值
    32. reference back() { return *(--end()); }
    33. const_reference back() const { return *(--end()); }
    34. // 交换
    35. void swap(list& x) { __STD::swap(node, x.node); }
    36. ...
    37. };
    38. template <class T, class Alloc>
    39. inline void swap(list& x, list& y)
    40. {
    41. x.swap(y);
    42. }

  • 相关阅读:
    Linux项目自动化构建工具-make/Makefile
    【C++】类与对象 第二篇(构造函数,析构函数,拷贝构造,赋值重载)
    利用iframe实现局部打印(区域打印)
    110道Java初级面试题及答案(最新Java初级面试题大汇总)
    Qt串口:QSerialPort、QSerialPortInfo
    【前端知识】Three 学习日志(一)—— Three.js 的简单尝试
    python读取文件并处理转化为list然后输出
    羽夏看Linux内核——引导启动(上)
    分享5款同类软件中的翘楚,属于是WIN10必备良品
    【Linux】万字总结Linux 基本指令,绝对详细!!!
  • 原文地址:https://blog.csdn.net/weixin_53459056/article/details/126914575