【STL】list

list相关文档:
http://www.cplusplus.com/reference/list/list/?kw=list

一、使用

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

构造函数(constructor)说明
list()构造空的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

list iterator

函数说明
begin + end返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代
rbegin + rend返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的reverse_iterator,即begin位置

下面代码是,反向迭代器,反向打印,反向迭代器遍历仍然是++

template<class T>
void printListIterator(const list<T>& l) {
	auto lit = l.rbegin();
	while (lit != l.rend()) {
		cout << *lit << " ";
		++lit;
	}
	cout << endl;
}
函数说明
empty检测list是否为空,是返回true,否则返回false
size返回list中有效节点的个数
front返回list的第一个节点中值的引用
back返回list的最后一个节点中值的引用
push_front在list首元素前插入值为val的元素
pop_front删除list中第一个元素
push_back在list尾部插入值为val的元素
pop_back删除list中最后一个元素
insert在list position 位置中插入值为val的元素
erase删除list position位置的元素
swap交换两个list中的元素
clear清空list中的有效元素
emplace_back在末尾构造并插入元素
spice将元素从参数的list转移到本list
unique删除重复值
merge合并排序列表

注意:

  1. unique使用的前提一定是该链表已经有序,merge使用的前提一定是两个链表都有序。
  2. spice和merge函数掉用后,作为这两个函数参数的两个list都将被清空。
※迭代器失效

  此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行 插入时是不会导致list的迭代器失效的只有在删除时才会失效 ,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

二、模拟list

结点类

// 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;
	}
	Self& operator--();
	Self& operator--(int);
	bool operator!=(const Self& l) {return _pNode != l._pNode;}
	bool operator==(const Self& l) {return _pNode != l._pNode;}
	
	PNode _pNode;
};

注:以下代码并没有写全,利用到了代码复用,如果读者有兴趣可以具体实现,

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&> const_iterator;
public:
	// List的构造
	list() {
		CreateHead();
	}
	list(int n, const T& value = T()) {
		CreateHead();
		for (int i = 0; i < n; ++i)
			push_back(value);
	}
	template <class Iterator>
	list(Iterator first, Iterator last) {
		CreateHead();
		while (first != last) {
			push_back(*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) {
		this->swap(l);
		return *this;
	}
	~list() {
		clear();
		delete _pHead;
		_pHead = nullptr;
	}
		……
		……
private:
	void CreateHead() {
		_pHead = new Node;
		_pHead->_pPre = _pHead;
		_pHead->_pNext = _pHead;
	}
private:
	PNode _pHead;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值