此处是带头双向链表
对于List,不像string、vector之类的,没有reserve的说法,也不支持[ ]和下标,只有一种方式遍历List也就是采用迭代器(范围for的底层也是迭代器)。
insert函数和erase函数(需要配合std库里面的find函数)
If no elements match, the function returns last.
cpp
void testlist1()
{
std::list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
std::list<int>::iterator pos = std::find(lt.begin(), lt.end(), 3);//std::find替换成find也可以正常运行
if (pos != lt.end())
{
lt.insert(pos, 30);
}
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
lt.erase(lt.begin());
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
}
sort函数
很少用,因为效率特别低。比如说List<int>类型,将每一个整型元素push_back到vector里面,再用标准库的sort函数来排序,然后将排好序的vector内的元素又重新push_back到List<int>当中的速度比直接采用List的sort成员函数来排序的速度要更快,
为什么list将sort函数单独拎出来做为一个成员函数,而不采用标准库里面的sort函数?
迭代器可以分为单向、双向、随机这三种类型。双向迭代器是兼容单向迭代器的,随机迭代器是兼容双向迭代器,List采用的是双向迭代器。而标准库的sort要求的是随机迭代器,无法适配,所以只能增加一个sort的成员函数。
list_node
cpp
template<class T>
struct list_node
{
list_node<T>* _next;
list_node<T>* _prev;
T _data;
list_node(const T& x = T())
:_next(nullptr)
, _prev(nullptr)//双向列表
, _data(x)
{}
};
list_node迭代器
cpp
// 1、迭代器要么就是原生指针
// 2、迭代器要么就是自定义类型对原生指针的封装,模拟指针的行为
template<class T, class Ref, class Ptr>
struct __list_iterator
{
typedef list_node<T> node;
typedef __list_iterator<T, Ref, Ptr> self;
node* _node;//本质上是对指针进行了封装
__list_iterator(node* n)
:_node(n)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(_node->_data);//返回值是T*
}
self& operator++()
{
_node = _node->_next;
return *this;
}
self operator++(int)//tmp出了该函数也销毁了,所以无法采用传引用返回
{
self tmp(*this);
_node = _node->_next;
return tmp;
}
self& operator--()
{
_node = _node->_prev;
return *this;
}
self operator--(int)
{
self tmp(*this);
_node = _node->_prev;
return tmp;
}
bool operator!=(const self& s)
{
return _node != s._node;//看底层封装的指针是否相同
}
bool operator==(const self& s)
{
return _node == s._node;
}
};
List封装
成员变量
cpp
template<class T>
class list
{
typedef list_node<T> node;
public:
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
private:
node* _head;//list类的唯一一个成员变量就是一个哨兵位头节点
}
begin()函数
cpp
iterator begin()
{
return iterator(_head->_next);
}
const_iterator begin() const
{
return const_iterator(_head->_next);
}
end()函数
cpp
iterator end()
{
return iterator(_head);
}
const_iterator end() const
{
return const_iterator(_head);
}
默认构造函数和empty_init()函数
cpp
void empty_init()
{
_head = new node;
_head->_next = _head;//自己的next指向自己
_head->_prev = _head;
}
list()
{
empty_init();
}
析构函数和clear()函数
cpp
void clear()
{
iterator it = begin();
while (it != end())
{
erase(it++);//
}
}
迭代器构造函数
cpp
template <class Iterator>
list(Iterator first, Iterator last)
{
empty_init();
while (first != last)
{
push_back(*first);//*first返回的是_node->_data;
++first;
}
}
拷贝构造
cpp
//传统写法
list(const list<T>& lt)
{
empty_init();
for (auto e : lt)
{
push_back(e);
}
}
//现代写法
list(const list<T>& lt)
{
empty_init();
list<T> tmp(lt.begin(), lt.end());//服用了迭代器构造函数
swap(tmp);
}
swap函数
cpp
void swap(list<T>& tmp)
{
std::swap(_head, tmp._head);
}
赋值运算符重载
cpp
list<T>& operator=(list<T> lt)//这里采用传值传参,形参是实参的一个拷贝
{
swap(lt);
return *this;
}
push_back()函数和push_front()函数
cpp
void push_back(const T& x)
{
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
pop_back()函数和pop_front()函数
cpp
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
insert()函数 Key
cpp
void insert(iterator pos, const T& x)
{
node* cur = pos._node;//迭代器封装的是指针
node* prev = cur->_prev;
node* new_node = new node(x);
prev->_next = new_node;//prev是指针,要修改*prev的成员变量就要采用指针。
new_node->_prev = prev;
new_node->_next = cur;
cur->_prev = new_node;
}
erase()函数 Key
cpp
iterator erase(iterator pos)
{
assert(pos != end());
node* prev = pos._node->_prev;
node* next = pos._node->_next;
prev->_next = next;
next->_prev = prev;
delete pos._node;
return iterator(next);
}