好! 不太想写CCF的题,那就再开一个吧
来 ! list,有了前面vector的基础,看list也轻松了很多,看来链表也是不是很难嘛
list优点就是插入删除方便,但是不能随机访问,因为不是连续的空间
1 基本数据结构
说到list,首先要看节点的数据结构
```C++
struct _List_node//双向链表, 源码没太看懂,书上是
{
pre;
next;
T data;
//
```
typedef _List_node<_Tp> _Node;
list中只有一个节点指针node,指向尾端的空白节点(超尾),最重要的是list居然是环状的!! ! 这样一个指针就可以解决所有的了,有趣
begin() -> node->next
end() -> node
empty() node == node->next
front() *(node->next)
back() *(–node)
2 迭代器
vector是连续空间,所以普通指针就可以了,但是list就复杂了一点,vector没有定义指针,就是value_type*类型的
list重新写了一个迭代器的class
```C++
template<typename _Tp>
struct _List_iterator
{
typedef _List_iterator<_Tp> _Self;
typedef _List_node<_Tp> _Node;
typedef ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;//双向迭代器
typedef _Tp value_type;
typedef _Tp* pointer;
typedef _Tp& reference;
__detail::_List_node_base* _M_node;//指向list节点的指针
//下面还重载了一些操作符 *(这个oprd好像我们自己是不能重载的,STL居然写了重载)== != -> ++ -- -- ++
```
list有个特性就是做任何操作,插入、删除,迭代器都不会失效,除了删除哪一个节点
3 基本操作
push_back()
调用insert(end(), x); 就是基本的链表操作
pop_back() pop_front()
tmp = end(); erase(–tmp);
clear()
循环destroy_node();
remove(value)
找到erase();
unique()
连续删除相同的,只保留一个
transfer(pos, first, last)
把[first,last)迁移到pos处,vector可能会麻烦些,但是list就很简单,只要把区间的两头连上就ok了,我就不写了
然后splic()、sort()、merge()都是基于transfer的
回宿舍再写吧
下面这些都是将x另一个链表接到本链表上
splice()
splice(pos, x); 调用transfer(pos, x.begin(), x.end());其他版本的我就不写了
merge()
merge是合并两个有序链表
reverse()
是不断把begin()后面那个用transfer()调到前面去
sort()
算法中的sort()要求随机访问迭代器,所以list不能使用sort,得写自己的sort
采用快排, 还没太看懂