STL模拟实现——list

文章介绍了C++标准库中的list容器,它是一种基于双向链表的数据结构,支持在任意位置的高效插入和删除操作。文章还详细阐述了list的迭代器使用,包括iterator和const_iterator,以及如何通过迭代器进行元素访问和遍历。此外,提供了一个简单的list模拟实现示例,展示了list的基本操作如push_back、pop_front等。
摘要由CSDN通过智能技术生成

list的介绍

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。

3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高 效。

4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。

5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)

list iterator的使用

list的使用可以参考——https://cplusplus.com/reference/list/list/?kw=list

list的模拟实现

#pragma once
#include<assert.h>
#include<iostream>
using namespace std;


namespace szg
{
	template<class T>
	struct list_node
	{
		list_node* _prev;
		list_node* _next;
		T _date;

		list_node(T x = T())
			:_prev(nullptr)
			,_next(nullptr)
			,_date(x)
		{}
	};

	template<class T, class  Ref, class Ptr>
	struct list_iterator
	{
		typedef list_iterator<T, Ref, Ptr>  Self;
		typedef list_node<T>  node;
		node* _pnode;

		list_iterator(node* x)
			:_pnode(x)
		{}

		Ref operator*()
		{
			return _pnode->_date;
		}

        Ptr operator->()
		{
			return &(_pnode->_date);
		}

		Self& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}

		Self operator++(int)
		{
			Self tmp(*this);
			_pnode = _pnode->_next;
			return tmp;
		}

		Self& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}

		Self operator--(int)
		{
			Self tmp(*this);
			_pnode = _pnode->_prev;
			return tmp;
		}

		bool operator!=(const Self& it)const
		{
			return _pnode != it._pnode;
		}

		bool operator==(const Self& it)const
		{
			return _pnode == it._pnode;
		}
	};

	template<class T>
	class list
	{
	public:
		typedef list_node<T>  node;
		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_iterator;

		list()
		{
			empty_initialize();
		}

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

		list(const list<T>& l)
		{
			empty_initialize();
			list<T> temp(l.begin(), l.end());
			swap(temp);
		}

		~list()
		{
			clear();
			delete _head;
		}

		list<T>& operator=(list<T> l)
		{
			swap(l);
			return *this;
		}

		void swap(list<T>& l)
		{
			std::swap(_head, l._head);
			std::swap(_size, l._size);
		}

		T& front()
		{
			assert(!empty());
			return _head->_next->_date;
		}

		T& back()
		{
			assert(!empty());
			return _head->_prev->_date;
		}

		const T& front()const
		{
			assert(!empty());
			return _head->_next->_date;
		}

		const T& back()const
		{
			assert(!empty());
			return _head->_prev->_date;
		}

		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);
		}

		size_t size()
		{
			return _size;
		}

		bool empty()const
		{
			return _size == 0;
		}

		iterator insert(iterator pos, const T& x)
		{
			node* newnode = new node(x);
			newnode->_prev = pos._pnode->_prev;
			newnode->_next = pos._pnode;
			pos._pnode->_prev->_next = newnode;
			pos._pnode->_prev = newnode;
			++_size;
			return iterator(newnode);
		}

		iterator erase(iterator pos)
		{
			assert(!empty());
			node* prev = pos._pnode->_prev;
			node* next = pos._pnode->_next;
			prev->_next = next;
			next->_prev = prev;
			delete pos._pnode;
			--_size;
			return iterator(next);
		}

		void push_back(const T& val)
		{
			insert(end(), val);
		}

		void push_front(const T& val)
		{
			insert(begin(), val);
		}

		void pop_back()
		{
			erase(--end());
		}

		void pop_front()
		{
			erase(begin());
		}

		void clear()
		{
			while (!empty())
			{
				pop_back();
			}
		}

	private:
		void empty_initialize()
		{
			_head = new node(T());
			_head->_prev = _head;
			_head->_next = _head;
			_size = 0;
		}
		node* _head;
		size_t _size;

	};

	template<class T>
	void print_list(const list<T>& lt)
	{
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test_list1()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_front(6);
		lt.push_front(7);

		// iterator 1、内嵌类型 2、行为像指针一样 
		print_list(lt);

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

		cout << lt.size() << endl;

		lt.pop_back();
		print_list(lt);
		lt.pop_front();
		print_list(lt);
		cout << lt.front() << endl;
		cout << lt.back() << endl;
		cout << lt.size() << endl;

		list<int> lt2(lt);

		print_list(lt2);

		lt.clear();
		print_list(lt);

		lt = lt2;
		print_list(lt);

		const list<int> lt3(lt);
		print_list(lt3);
	}




	void test_list()
	{
		test_list1();
	}

}

在代码中也列出了测试的例子。

list的迭代器

list的迭代器使得可以使用统一的方式去遍历访问不同的数据结构。

常用的迭代器有两种,一种是iterator,还有一种是const_iterator。list的迭代器与vector和string不一样,后者可以使用原生指针,但是list只能使用类模板封装和运算符重载。这里我们还用到了使用模板参数来进行模板的复用,比如我们要生成iterator和const_iterator模板:

第一种方法如下:

    template<class T>
	struct __list_iterator
	{
		typedef list_node<T> node;
		node* _pnode;

		__list_iterator(node* p)
			:_pnode(p)
		{}

		T& operator*()
		{
			return _pnode->_data;
		}

		__list_iterator<T>& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}

		__list_iterator<T>& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}

		bool operator!=(const __list_iterator<T>& it)
		{
			return _pnode != it._pnode;
		}
	};
    template<class T>
	struct __list_const_iterator
	{
		typedef list_node<T> node;
		node* _pnode;

		__list_const_iterator(node* p)
			:_pnode(p)
		{}

		const T& operator*()
		{
			return _pnode->_data;
		}

		__list_const_iterator<T>& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}

		__list_const_iterator<T>& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}

		bool operator!=(const __list_const_iterator<T>& it)
		{
			return _pnode != it._pnode;
		}
	};

需要两段代码,并且两段代码之间的差距极小,费了那么大的劲儿就为了把T&改成const  T&,所以有了第二种方法。

template<class T, class  Ref, class Ptr>
	struct list_iterator
	{
		typedef list_iterator<T, Ref, Ptr>  Self;
		typedef list_node<T>  node;
		node* _pnode;

		list_iterator(node* x)
			:_pnode(x)
		{}

		Ref operator*()
		{
			return _pnode->_date;
		}

        Ptr operator->()
		{
			return &(_pnode->_date);
		}

		Self& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}

		Self operator++(int)
		{
			Self tmp(*this);
			_pnode = _pnode->_next;
			return tmp;
		}

		Self& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}

		Self operator--(int)
		{
			Self tmp(*this);
			_pnode = _pnode->_prev;
			return tmp;
		}

		bool operator!=(const Self& it)const
		{
			return _pnode != it._pnode;
		}

		bool operator==(const Self& it)const
		{
			return _pnode == it._pnode;
		}
	};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JDSZGLLL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值