C++——list

什么是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定义

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

迭代器的使用

begin() 返回第一个元素的迭代器
end() 返回最后一个元素下一个位置的迭代器
rbegin() 返回第一个元素的reverse_iterator,即end位置
rend() 返回最后一个元素下一个位置的reverse_iterator,即begin位置
cbegin() (C++11) 返回第一个元素的cosnt_iterator
cend() (C++11) 返回最后一个元素下一个位置的const_iterator
crbegin() (C++11) 即crend()位置
crend() (C++11) 即crbegin()位置

这里需要注意的是:

1.begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
2 rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动
3 cbegin与cend为const的正向迭代器,与begin和end不同的是:该迭代器指向节点中的元素值不能修

4 crbegin与crend为const的反向得带器,与rbegin和rend不同的是:该迭代器指向节点中的元素值不
能修改

bool empty() const 检测list是否为空,是返回true,否则返回false
size_t size() const 返回list中有效节点的个数
reference front() 返回list的第一个节点中值的引用
const_reference front() const 返回list的第一个节点中值的const引用
reference back() 返回list的最后一个节点中值的引用
const_reference back() const 返回list的最后一个节点中值的const引用

增删查改

void push_front (const value_type& val) 在list首元素前插入值为val的元素
void pop_front() 删除list中第一个元素
void push_back (const value_type& val) 在list尾部插入值为val的元素
void pop_back() 删除list中最后一个元素
template <class… Args>
void emplace_front (Args&&… args) (C++11)
在list第一个元素前根据参数直接构造元素
template <class… Args>
void emplace_back (Args&&… args) (C++11)
在list最后一个元素后根据参数直接构造元素
template <class… Args>
iterator emplace( const_iterator position, Args&&… args)
(C++11)
在链表的任意位置根据参数直接构造元素
iterator insert (iterator position, const value_type& val) 在list position 位置中插入值为val的元素
void insert (iterator position, size_type n, const value_type&
val)
在list position位置插入n个值为val的元素
void insert (iterator position, InputIterator first, InputIterator
last)
在list position位置插入[first, last)区间中元素
iterator erase (iterator position) 删除list position位置的元素
iterator erase (iterator first, iterator last) 删除list中[first, last)区间中的元素
void swap (list& x) 交换两个list中的元素
void resize (size_type n, value_type val = value_type())
将list中有效元素个数改变到n个,多出的元素用val填充
void clear() 清空list中的有效元素

模拟实现

namespace bit
{
 // List的节点类
 template<class T>
 struct ListNode
 {
 	ListNode(const T& val = T())
	 : _pPre(nullptr)
	 , _pNext(nullptr)
	 , _val(val)
 	{}
	 ListNode<T>* _pPre;
	 ListNode<T>* _pNext;
	 T _val;
 };
 /*
 List 的迭代器
 迭代器有两种实现方式:
 1. 原生态指针,比如:vector
 2. 将原生态指针进行封装,因迭代器的使用形式与指针完全相同,因此,在自定义的类中必须实现以下方
法:
 1. 指针可以解引用,迭代器的类中必须重载operator*()
 2. 指针可以通过->访问其所指空间成员,迭代器类中必须重载oprator->()
 3. 指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int)
 至于operator--()/operator--(int)释放需要重载,根据具体的结构来抉择,双向链表可以向前
移 动,所以需要重载,如果是forward_list就不需要重载--
 4. 迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()
 */
 template<class T, class Ref, class Ptr>
 class ListIterator
 {
	typedef ListNode<T>* PNode;
 	typedef ListIterator<T, Ref, Ptr> Self;
 public:
 ListIterator(PNode pNode = nullptr)
 	: _pNode(pNode)
 {}
 ListIterator(const Self& l)
 	: _pNode(l._pNode)
 {}
 T& operator*()
 {
 	return _pNode->_val;
 }
 T* operator->()
 {
 	return &(operator*());
 }
 Self& operator++()
 {
	 _pNode = _pNode->_pNext;
	 return *this;
 }
 
 Self operator++(int)
 {
	 Self temp(*this);
	 _pNode = _pNode->_pNext;
	 return temp;
 }
 bool operator!=(const Self& l)
 {
 	return _pNode != l._pNode;
 }
 bool operator==(const Self& l)
 {
 	return _pNode != l._pNode;
 }
 PNode _pNode;
 };
 
 /*
 List 的反向迭代器,反向迭代器与正向迭代器刚好是相反的,反向迭代器++,迭代器往前移动,反向迭代
器--, 迭代器往后移动,因此反向迭代器可以在正向迭代器的基础之上来实现
 */
 template<class T, class Ref, class Ptr, class Iterator>
 class ListReverseIterator
 {
 	typedef ListReverseIterator<T, Ref, Ptr, Iterator> Self;
 public:
 	ListReverseIterator(const Iterator& it)
 		: _it(it)
 	{}
	ListIterator(const Self& l)
	 	: _pNode(l._pNode)
	 {}
	 T& operator*()
	 {
	 	return _pNode->_val;
	 }
	 T* operator->()
	 {
	 	return &(operator*());
	 }
	 Self& operator++()
	 {
		 _pNode = _pNode->_pNext;
		 return *this;
	 }
 
	 Self operator++(int)
	 {
		 Self temp(*this);
		 _pNode = _pNode->_pNext;
		 return temp;
	 }
	 bool operator!=(const Self& l)
	 {
	 	return _pNode != l._pNode;
	 }
	 bool operator==(const Self& l)
	 {
	 	return _pNode != l._pNode;
	 }
 	 PNode _pNode;
 };
 
 /*
 List 的反向迭代器,反向迭代器与正向迭代器刚好是相反的,反向迭代器++,迭代器往前移动,反向迭代
器--, 迭代器往后移动,因此反向迭代器可以在正向迭代器的基础之上来实现
 */
 template<class T, class Ref, class Ptr, class Iterator>
 class ListReverseIterator
 {
 	typedef ListReverseIterator<T, Ref, Ptr, Iterator> Self;
 public:
 ListReverseIterator(const Iterator& it)
 	: _it(it)
 {}
ListReverseIterator(const Self& s)
 	: _it(s._it)
 {}
 Ref operator*()
 {
 	Iterator temp = _it;
 	return *(--temp);
 }
 Ptr operator->()
 {
 	return &operator*();
 }
 // 反向迭代器的++,就是正向迭代器的--
 Self& operator++()
 {
	 --_it;
	 return *this;
 }
 Self operator++(int)
 {
	 Iterator temp(_it);
	 --_it;
	 return temp;
 }
 // 反向迭代器的--,就是正向迭代器的++
 Self& operator--()
 {
	 ++_it;
	 return *this;
 }
 Self operator--(int)
 {
	 Iterator temp(_it);
	 ++_it;
	 return temp;
 }
 bool operator!=(const Self& s)
 {
 	return _it != s._it;
 }
 bool operator==(const Self& s)
 {
 	return _it == s._it;
 }
private:
 	Iterator _it;
 };
 template<class T>
 class List
 {
 	typedef ListNode<T> Node;
 	typedef Node* PNode;
 public:
	 typedef ListIterator<T, T&, T*> Iterator;
	 typedef ListIterator<T, const T&, const T&> ConstIterator;
	 typedef ListReverseIterator<T, T&, T*, Iterator> ReverseIterator;
	 typedef ListReverseIterator<T, const T&, const T*, ConstIterator> ConstReverseIterator;
 public:
 ///
 // List的构造
 List()
 {
	 CreateHead();
 }
 List(int n, const T& value = T())
 {
	 CreateHead();
	 for (int i = 0; i < n; ++i)
	 PushBack(value);
 }
 template <class Iterator>
 List(Iterator first, Iterator last)
 {
	 CreateHead();
	 while (first != last)
	 {
		 PushBack(*first);
		 ++first;
	 }
 }
 List(const List<T>& l)
 {
	 CreateHead();
	 // 用l中的元素构造临时的temp,然后与当前对象交换
	 List<T> temp(l.CBegin(), l.CEnd());
	 this->Swap(temp);
 }
 List<T>& operator=(const List<T>& l)
{
	 if (this != &l)
	 {
		 List<T> temp(l);
		 this->Swap(temp);
	 }
	 return *this;
 }
 ~List()
 {
	 Clear();
	 delete _pHead;
	 _pHead = nullptr;
 }
 ///
 // List Iterator
 Iterator Begin()
 {
 	return Iterator(_pHead->_pNext);
 }
 Iterator End()
 {
 	return Iterator(_pHead);
 }
 ReverseIterator RBegin()
 {
 	return ReverseIterator(End());
 }
 ReverseIterator REnd()
 {
 	return ReverseIterator(Begin());
 }
 ConstIterator CBegin()const
 {
 	return ConstIterator(_pHead->_pNext);
 }
 ConstIterator CEnd()const
 {
 	return ConstIterator(_pHead);
 }
 ConstReverseIterator CRBegin()const
 {
 	return ConstReverseIterator(CEnd());
 }
ConstReverseIterator CREnd()const
 {
 	return ConstReverseIterator(CBegin());
 }
 ///
 // List Capacity
 size_t Size()const
 {
	 size_t count = 0;
	 PNode pCur = _pHead->_pNext;
	 while (pCur != _pHead)
	 {
		 ++count;
		 pCur = pCur->_pNext;
	 }
	 return count;
 }
 bool Empty()const
 {
		 return _pHead->_pNext == _pHead;
 }
 void ReSize(size_t newSize, const T& val = T())
 {
	 size_t oldSize = Size();
	 if (oldSize <= newSize)
	 {
		 for (size_t i = oldSize; i < newSize; ++i)
		 PushBack(val);
	 }
	 else
	 {
		 for (size_t i = newSize; i < oldSize; ++i)
		 PopBack();
 	 }
 }
 
 // List Access
 T& Front()
 {
 	return _pHead->_pNext->_val;
 }
 const T& Front()const
 {
 	return _pHead->_pNext->_val;
 }
 T& Back()
 {
	return _pHead->_pPre->_val;
 }
 const T& Back()const
 {
 	return _pHead->_pPre->_val;
 }
 
 // List Modify
 void PushBack(const T& val)
 {
	 PNode pNewNode = new Node(val);
	 // 先把新节点尾插进去
	 pNewNode->_pNext = _pHead;
	 pNewNode->_pPre = _pHead->_pPre;
	 // 再链接剩余两个指针
	 _pHead->_pPre = pNewNode;
	 pNewNode->_pPre->_pNext = pNewNode;
 }
 // 尾删
 void PopBack()
 {
	 // 找到待删除节点
	 PNode pDel = _pHead->_pPre;
	 if (pDel != _pHead)
	 {
		 _pHead->_pPre = pDel->_pPre;
		 pDel->_pPre->_pNext = _pHead;
		 delete pDel;
	 }
 }
 // 头插
 void PushFront(const T& val)
 {
	 PNode pNewNode = new Node(val);
	 // 先把新节点尾插进去
	 pNewNode->_pNext = _pHead->_pNext;
	 pNewNode->_pPre = _pHead;
	 // 再链接剩余两个指针
	 _pHead->_pNext = pNewNode;
	 pNewNode->_pNext->_pPre = pNewNode;
 }
 // 头删
 void PopFront()
 {
	 // 找到待删除节点
	 PNode pDel = _pHead->_pNext;
	 if (pDel != _pHead)
	 {
		 _pHead->_pNext = pDel->_pNext;
		 pDel->_pNext->_pPre = _pHead;
		 delete pDel;
		 }
 }
 // 在pos位置前插入值为val的节点
 Iterator Insert(Iterator pos, const T& val)
 {
	 PNode pNewNode = new Node(val);
	 PNode pCur = pos._pNode;
	 // 先将新节点插入
	 pNewNode->_pPre = pCur->_pPre;
	 pNewNode->_pNext = pCur;
	 pNewNode->_pPre->_pNext = pNewNode;
	 pCur->_pPre = pNewNode;
	 return Iterator(pNewNode);
 }
 // 删除pos位置的节点,返回该节点的下一个位置
 Iterator Erase(Iterator pos)
 {
	 // 找到待删除的节点
	 PNode pDel = pos._pNode;
	 PNode pRet = pDel->_pNext;
	 // 将该节点从链表中拆下来并删除
	 pDel->_pPre->_pNext = pDel->_pNext;
	 pDel->_pNext->_pPre = pDel->_pPre;
	 delete pDel;
	 return Iterator(pRet);
 }
 void Clear()
 {
 	PNode pCur = _pHead->_pNext;
 	while (pCur != _pHead)
 	{
	 	_pHead->_pNext = pCur->_pNext;
	 	delete pCur;
	 	pCur = _pHead->_pNext;
 	}
 	_pHead->_pNext = _pHead;
 	_pHead->_pPre = _pHead;
 }
 void Swap(List<T>& l)
 {
 	swap(_pHead, l._pHead);
 }
 private:
 void CreateHead()
 {
	 _pHead = new Node;
	 _pHead->_pPre = _pHead;
	 _pHead->_pNext = _pHead;
 }
 private:
	 PNode _pHead;
 };
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值