C++利器STL——list详解

要努力,但不要着急,繁花锦簇,硕果累累都需要过程!

 

目录

1.list介绍及使用

1.1list介绍:

1.2list的使用:

2.list的模拟实现

3.list与vector的区

1.list介绍及使用

1.1list介绍:

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3.list最大的缺陷是不支持 任意位置 的随机访问

1.2list的使用:

1.2.1list的构造:
list()
构造空的list
list (size_type n, const value_type& val = value_type())
构造的list中包含n个值为val的元素
list (InputIterator fifirst, InputIterator last)
用[first, last)区间中的元素构造list
list (const list& x)
拷贝构造函数

 1.2.2list iterator的使用:

begin()+end()
返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
rebegin+rend()
返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的
reverse_iterator,即begin位置

注:

1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

1.2.3list modify:

push_back
在list尾部插入值为val的元素
pop_back
删除list中最后一个元素
insert
在list position 位置中插入值为val的元素
erase
删除list position位置的元素
swap
交换两个list中的元素
clear
清空list中的有效元素
push_front
在list首元素前插入值为val的元素
pop_front
删除list中第一个元素

 

1.2.4list capacity:

empty
检测list是否为空,是返回true,否则返回false
size
返回list中有效节点的个数

1.2.5operatoin:

remove删除指定元素
sort对数据进行排序
unique去掉重复元素的数据

 

 注:list不能使用算法库里面的sort

 原因:

list底层使用的是双向链表的方式,sort底层在实现的时候使用了指针-指针的方式,而list不能通过指针-指针的方式得到中间元素的个数 

2.list的模拟实现

#include<iostream>
#include<assert.h>
using namespace std;
namespace lt
{
	template<typename T>
	struct list_node
	{
		list_node* _next;
		list_node* _prev;
		T _data;
		list_node(const T& val)
			:_next(nullptr),
			_prev(nullptr),
			_data(val)
		{};
	};
	//template<typename 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<typename 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;
	//	}
	//};
	template<typename T, typename ref, typename ptr>
	struct __list_iterator
	{
		typedef list_node<T> node;
		typedef __list_iterator<T, ref, ptr> self;
		node* _pnode;
		__list_iterator(node* p)
			:_pnode(p)
		{}
		ref& operator*()
		{
			return _pnode->_data;
		}
		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;
		}
		ptr operator->()
		{
			return &_pnode->_data;
		}
		bool operator!=(const self& it)const
		{
			return _pnode != it._pnode;
		}
	};
	template <typename T>
	class list
	{
		typedef list_node<T> node;
	public:
		//typedef __list_iterator<T> iterator;
		//typedef __list_const_iterator<T> const_iterator;
		//typedef __list_iterator<T, T&> iterator;
		//typedef __list_iterator<T, const T&> const_iterator;
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;
		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);
		}
		void empty_initalize()
		{
			_head = new node(T());
			_head->_next = _head;
			_head->_prev = _head;
		}
		list()
		{
			empty_initalize();
		}
		//传统写法
		//list(const list<T>& lt)
		//{
		//	empty_initalize();
		//	for (auto& e : lt)
		//	{
		//		push_back(e);
		//	}
		//}
		template <class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			empty_initalize();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		void swap(list<T>& lt)
		{
			std::swap(_head, lt._head);
			std::swap(_size, lt._size);

		}
		//拷贝构造现代写法:
		list(const list<T>& lt)
		{
			empty_initalize();
			list<T> tmp(lt.begin(), lt.end());
			swap(tmp);
		}
		//list<T>& operator=(const list<T>& lt)
		//{
		//	if (this != &lt)
		//	{
		//		clear();
		//		for (auto& e : lt)
		//		{
		//			push_back(e);
		//		}
		//	}
		//	return *this;
		//}
		//赋值重载现代写法:
		list<T>& operator=(list<T> lt)
		{
			swap(lt);
			return *this;
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}
		void push_back(const T& val)
		{
			insert(end(), val);
		}
		void push_front(const T& val)
		{
			insert(begin(), val);
		}
		void pop_back()
		{
			erase(--end());
			--_size;
		}
		void pop_front()
		{
			erase(begin());
		}
		size_t size() const
		{
			return _size;
		}
		bool empty()const
		{
			return _size == 0;
		}
		iterator insert(iterator pos, const T& val)
		{
			node* newnode = new node(val);
			node* cur = pos._pnode;
			node* prev = cur->_prev;
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			_size++;
			return iterator(newnode);
		}
		iterator erase(iterator pos)
		{
			assert(pos != end());
			node* prev = pos._pnode->_prev;
			node* next = pos._pnode->_next;
			prev->_next = next;
			next->_prev = prev;
			delete pos._pnode;
			_size--;
			return iterator(next);
		}
	private:
		node* _head;
		size_t _size;
	};

3.list与vector的区别

vectorlist
底层结构
动态顺序表,一段连续空间
带头结点的双向循环链表
随机访问
支持随机访问,访问某个元素效率O(1)
不支持随机访问,访问某个元素
效率O(N)
插入和删除
任意位置插入和删除效率低,需要搬移元素,时间复杂
度为O(N),插入时有可能需要增容,增容:开辟新空
间,拷贝元素,释放旧空间,导致效率更低
任意位置插入和删除效率高,不
需要搬移元素,时间复杂度为
O(1)
空间利用率
底层为连续空间,不容易造成内存碎片,空间利用率
高,缓存利用率高
底层节点动态开辟,小节点容易 造成内存碎片,空间利用率低, 缓存利用率低
迭代器
原生态指针
对原生态指针(节点指针)进行封装
迭代器失效
在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效
插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响
使用场景
需要高效存储,支持随机访问,不关心插入删除效率
大量插入和删除操作,不关心随 机访问

  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

linkindly

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

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

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

打赏作者

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

抵扣说明:

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

余额充值