【C++】list的模拟实现

list 的常见接口介绍

  1. 构造函数
函数名称 功能说明
list() 构造空的list
list(const list& x) 拷贝构造
list(InputIterator first, InputIterator last) 用迭代器区间构造list
list(int n, const T& val = T()) 用 n 个 val 元素构造list
  1. 遍历及访问操作
函数名称 功能说明
begin() 返回第一个元素的迭代器
end() 返回最后一个元素下一个位置的迭代器
rbegin() 返回 end() 位置的反向迭代器
rend() 返回 begin() 位置的反向迭代器
front() 获取 list 中第一个元素的引用
back() 获取 list 中最后一个元素的引用
  1. 容量操作
函数名称 功能说明
empty() 判断 list 是否为空
size() 返回 list 中有效节点的个数
  1. 修改操作
函数名称 功能说明
push_front(const T& val) 在 list 第一个元素之前插入 val 元素
push_back(const T& val) 在 list 最后一个元素之后插入 val 元素
pop_front() 删除 list 中的第一个节点
pop_back() 删除 list 中的最后一个节点
insert(iterator pos, const T& val) 在 pos 位置插入 val 元素
erase(iterator pos) 删除 pos 位置的节点
swap(list& lt) 两个 ilst 进行相互交换
clear() 清除 list 中的有效节点

list 的模拟实现

#pragma once
#include 

namespace zs
{
	template<class T>
	class list_node
	{
	public:
		list_node(const T& val = T())
			: _data(val)
			, _next(nullptr)
			, _prev(nullptr)
		{}
	public:
		T _data;
		list_node<T>* _next;
		list_node<T>* _prev;
	};
	
	// 反向迭代器
	template<class Iterator, class Ref, class Ptr>
	class __reverse_iterator
	{
	public:
		typedef __reverse_iterator<Iterator, Ref, Ptr> reverse_iterator;
	public:
		__reverse_iterator(Iterator it)
			:_cur(it)
		{}

		reverse_iterator& operator++()
		{
			--_cur;
			return *this;
		}

		reverse_iterator& operator--()
		{
			++_cur;
			return *this;
		}

		reverse_iterator operator++(int)
		{
			reverse_iterator tmp = *this;
			--_cur;
			return tmp;
		}

		reverse_iterator operator--(int)
		{
			reverse_iterator tmp = *this;
			++_cur;
			return tmp;
		}

		Ref operator*()
		{
			Iterator tmp = _cur;
			--tmp;
			return *tmp;
		}

		Ptr operator->()
		{
			return &(operator*());
		}

		bool operator!=(const reverse_iterator& it)
		{
			return _cur != it._cur;
		}

		bool operator==(const reverse_iterator& it)
		{
			return _cur == it._cur;
		}
	public:
		Iterator _cur;
	};
	
	// 正向迭代器
	template<class T, class Ref, class Ptr>
	class __list_iterator
	{
	private:
		typedef list_node<T> Node;
		typedef __list_iterator<T, Ref, Ptr> iterator;
	public:
		__list_iterator(Node* node)
			: _node(node)
		{}

		bool operator!=(const iterator& it) const
		{
			return _node != it._node;
		}

		bool operator==(const iterator& it) const
		{
			return _node == it._node;
		}

		Ref operator*()
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &(operator*());
		}

		iterator& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		iterator operator++(int)
		{
			iterator ret(*this);
			_node = _node->_next;
			return ret;
		}

		iterator& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		iterator operator--(int)
		{
			iterator ret(*this);
			_node = _node->_prev;
			return ret;
		}
	public:
		Node* _node;
	};

	template<class T>
	class list
	{
	private:
		typedef list_node<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;
		typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;
		typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

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

		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

		const_reverse_iterator rbegin() const
		{
			return const_reverse_iterator(end());
		}

		const_reverse_iterator rend() const
		{
			return const_reverse_iterator(begin());
		}
	public:
		list()
		{
			empty_init();
		}
		template <class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		list(const list<T>& lt)
		{
			empty_init();
			list<T> tmpList = list(lt.begin(), lt.end());
			swap(tmpList);
		}
		list(int n, const T& val = T())
		{
			empty_init();
			int i = 0;
			while(i++ < n)
			{
				push_back(val);
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
		list<T>& operator=(list<T> lt)
		{
			swap(lt);
			return *this;
		}
		void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		void swap(list<T>& lt)
		{
			::swap(_head, lt._head);
		}

		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}
		void push_front(const T& val)
		{
			insert(begin(), val);
		}
		void push_back(const T& val)
		{
			insert(end(), val);
		}
		void pop_front()
		{
			erase(begin());
		}
		void pop_back()
		{
			erase(-end());
		}
		iterator insert(iterator pos, const T& val)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;

			Node* newnode = new Node(val);

			prev->_next = newnode;
			newnode->_prev = prev;
			cur->_prev = newnode;
			newnode->_next = cur;

			return iterator(newnode);
		}
		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;

			delete cur;

			return iterator(next);
		}

		T& front()
		{
			return *(begin());
		}
		T& back()
		{
			return *(--end());
		}
		const T& front() const
		{
			return *(begin());
		}
		const T& back() const
		{
			return *(--end());
		}

		bool empty() const
		{
			return _head->_next == _head;
		}
		size_t size() const
		{
			size_t count = 0;
			list<T>::const_iterator it = begin();
			while (it != end())
			{
				++it;
				++count;
			}
			return count;
		}
	private:
		Node* _head;
	};
}

list 与 vector 的对比

vector 与 list 都是重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不尽相同,其主要不同如下:

vector list
底层结构 动态顺序表,一段连续空间 带头结点的双向循环链表
随机访问 支持随机访问 不支持随机访问,访问某个元素的效率是O(N)
插入和删除 任意位置插入删除效率低,时间复杂度是O(N);插入时可能还需要增容,导致效率更低 任意位置插入删除效率高,时间复杂度是O(1)
空间利用率 底层为连续空间,不容易造成内存碎片,缓存利用率高,空间利用率高 底层动态开辟小节点,缓存利用率低,空间利用率低
迭代器 原生态指针 对原生态指针进行封装
迭代器失效 插入元素时,可能导致扩容,使原来的迭代器失效;删除元素时,当前迭代器会失效 插入元素不会导致迭代器失效,删除元素会导致当前迭代器失效
使用场景 需要高效存储,支持随机访问,不关心插入删除效率 需要大量插入删除操作,不关心随机访问

你可能感兴趣的:(C++,c++,list)