STL —— list

2024-05-13 1139阅读
STL —— list

博主首页: 有趣的中国人

专栏首页: C++专栏


    本篇文章主要讲解 list模拟实现的相关内容

    1. list简介

    列表(list)是C++标准模板库(STL)中的一个容器,它是一个双向链表数据结构,用于存储元素。与vector不同,列表中的元素在内存中不是连续存储的,而是通过指针相互连接形成链表。这种设计使得列表对于插入和删除操作非常高效,但是在查找特定元素时相对较慢,因为需要按序遍历整个链表。


      2. list模拟实现

      2.1 list类的相关成员变量

      在C++的标准库中,list的实现方式是带头双向循环链表,因此在类中,我们需要一个头指针_head。至于每个节点,我们也同样需要构造一个类,其中成员变量包含_prev, _next和数据_val。

      template
      struct ListNode
      {
      	ListNode* _prev;
      	ListNode* _next;
      	T _val;
      	ListNode(const T& x = T())
      		:_prev(nullptr)
      		,_next(nullptr)
      		,_val(x)
      	{}
      };
      template
      class list
      {
      public:
      	typedef ListNode Node;
      	list()
      	{
      		_head = new Node;
      		_head->_prev = _head;
      		_head->_next = _head;
      	}
      private:
      	Node* _head;
      };
      

        2.2 尾插

        尾插太简单了,直接上代码:

        void push_back(const T& x)
        {
        	Node* newnode = new Node(x);
        	Node* tail = _head->_prev;
        	tail->_next = newnode;
        	newnode->_prev = tail;
        	newnode->_next = _head;
        	_head->_prev = newnode;
        }
        

          2.3 迭代器

          在库中,我们不管迭代器的底层是如何实现的,但是我们都要用相同的方法使用迭代器,例如之前讲过的 vector,string,在g++中的实现方法就是原生指针,来实现例如++、--、*等功能,但是这里list由于不是连续存储的,所以用原生指针正常的++、--等功能并不能达到我们的预期,因此我们可以把迭代器搞成一个类类型,并用运算符重载来改变它的功能。

          下面的代码是迭代器正常的使用方法,我们需要用运算符重载来实现这些功能:
          void list_test1()
          {
          	list lt;
          	lt.push_back(1);
          	lt.push_back(2);
          	lt.push_back(3);
          	lt.push_back(4);
          	lt.push_back(5);
          	list::iterator it = lt.begin();
          	while (it != lt.end())
          	{
          		cout 
          	typedef ListNode}
          };
          
          	typedef ListNode}
          	T& operator*()
          	{
          		return _node-_val;
          	}
          	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;
          	}
          	bool operator!=(const Self& it)
          	{
          		return _node != it._node;
          	}
          };
          

            2.3.3 insert 和 erase

            insert和erase传的参数就是iterator,模拟实现代码如下:

            void insert(iterator pos, const T& x)
            {
            	Node* newnode = new Node(x);
            	Node* cur = pos._node;
            	Node* prev = cur->_prev;
            	prev->_next = newnode;
            	newnode->_prev = prev;
            	newnode->_next = cur;
            	cur->_prev = newnode;
            }
            void erase(iterator pos)
            {
            	Node* cur = pos._node;
            	Node* prev = cur->_prev;
            	Node* next = cur->_next;
            	prev->_next = next;
            	next->_prev = prev;
            	delete cur;
            	cur = nullptr;
            }
            
            这里需要注意,在erase的时候由于迭代器指向的空间被释放了,会导致迭代器失效的问题,之前的文章讲过相关的内容,因此我们需要更新iterator,指向被删除的位置的下一个位置即可,代码如下:
            iterator erase(iterator pos)
            {
            	Node* cur = pos._node;
            	Node* prev = cur->_prev;
            	Node* next = cur->_next;
            	prev->_next = next;
            	next->_prev = prev;
            	delete cur;
            	cur = nullptr;
            	return next;
            }
            

              2.3.4 begin 和 end

              begin 和 end是在迭代器中的成员函数,返回头和尾的迭代器即可:

              typedef ListNodeIterator iterator;
              iterator begin()
              {
              	return iterator(_head->_next);
              	// 单参数类型的构造函数支持隐式类型转换,以下依法也可以:
              	// return _head->_next;
              }
              iterator end()
              {
              	return iterator(_head);
              	// return _head;
              }
              

                2.3.5 insert 和 erase的复用

                push_back、push_front、pop_back、pop_front都可以复用insert和erase,代码如下:

                void push_back(const T& x)
                {
                	/*Node* newnode = new Node(x);
                	Node* tail = _head->_prev;
                	tail->_next = newnode;
                	newnode->_prev = tail;
                	newnode->_next = _head;
                	_head->_prev = newnode;*/
                	insert(end(), x);
                }
                void pop_back()
                {
                	erase(--end());
                }
                void push_front(const T& x)
                {
                	insert(begin(), x);
                }
                void pop_front()
                {
                	erase(begin());
                }
                

                测试代码:

                void list_test1()
                {
                	list lt;
                	lt.push_back(1);
                	lt.push_back(2);
                	lt.push_back(3);
                	lt.push_back(4);
                	lt.push_back(5);
                	list::iterator it = lt.begin();
                	while (it != lt.end())
                	{
                		cout 
                		cout 
                		cout 
                		cout 
                	struct A
                	{
                		int _a1;
                		int _a2;
                		A(int a1 = 0, int a2 = 0)
                			:_a1(a1)
                			,_a2(a2)
                		{}
                	};
                	list 5,6 });
                	list
                		// 主要看这里
                		cout 
                	return &_node-_val;
                }
                
                	struct A
                	{
                		int _a1;
                		int _a2;
                		A(int a1 = 0, int a2 = 0)
                			:_a1(a1)
                			,_a2(a2)
                		{}
                	};
                	/*A* aa;
                	(*aa)._a1;
                	aa-_a1;*/
                	list 5,6 });
                	list
                		cout 
                	list
                		cout 
                	list
                	return iterator(_head-_next);
                	// 单参数类型的构造函数支持隐式类型转换,以下写法也可以:
                	// return _head-_next;
                }
                iterator end() const
                {
                	return iterator(_head);
                	// return _head;
                }
                void Print(const list
                	list
                		// 这里可以修改
                		*it += 10;
                		cout 
                	list
                	return iterator(_head-_next);
                	// 单参数类型的构造函数支持隐式类型转换,以下写法也可以:
                	// return _head-_next;
                }
                const iterator end() 
                {
                	return iterator(_head);
                	// return _head;
                }
                
                	typedef ListNode}
                	const T& operator*()
                	{
                		return _node-_val;
                	}
                	const T* operator-()
                	{
                		return &_node-_val;
                	}
                	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;
                	}
                	bool operator!=(const Self& it)
                	{
                		return _node != it._node;
                	}
                };
                
                	return const_iterator(_head-_next);
                	// 单参数类型的构造函数支持隐式类型转换,以下写法也可以:
                	// return _head-_next;
                }
                const_iterator end() const
                {
                	return const_iterator(_head);
                	// return _head;
                }
                
                	typedef ListNode}
                	Ref operator*()
                	{
                		return _node-_val;
                	}
                	Ptr operator-()
                	{
                		return &_node-_val;
                	}
                	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;
                	}
                	bool operator!=(const Self& it)
                	{
                		return _node != it._node;
                	}
                };
                template
                public:
                	typedef ListNode
                		return iterator(_head-_next);
                		// 单参数类型的构造函数支持隐式类型转换,以下写法也可以:
                		// return _head-_next;
                	}
                	iterator end() 
                	{
                		return iterator(_head);
                		// return _head;
                	}
                	const_iterator begin() const
                	{
                		return const_iterator(_head-_next);
                		// 单参数类型的构造函数支持隐式类型转换,以下写法也可以:
                		// return _head-_next;
                	}
                	const_iterator end() const
                	{
                		return const_iterator(_head);
                		// return _head;
                	}
                	// ......
                };
                
                	iterator it = begin();
                	while (it != end())
                	{
                		it = erase(it);
                	}
                }
                ~list()
                {
                	clear();
                	delete _head;
                	_head = nullptr;
                }
                
                	_head = new Node;
                	_head-_prev = _head;
                	_head-_next = _head;
                }
                list(const list
                	empty_init();
                	for (auto& e : lt)
                	{
                		push_back(e);
                	}
                }
                
                	std::swap(_head, lt._head);
                }
                list
                	swap(lt);
                	return *this;
                }
                
                VPS购买请点击我

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

                目录[+]