【C++】list容器的入门及其模拟实现
介绍
在导入头文件<list>之后,我们就可以使用C++内置的list库来使用链表
#include<list>
特点
1.双向迭代:
<list>
在有头节点的情况下提供了双向迭代器,可以向前或者向后遍历元素2.动态大小:
<list>
的大小可以动态变化,不需要预先分配固定大小的内存3.快速插入和删除:可以在列表的任何位置快速插入或删除元素,而不需要像向量那样移动大量元素
声明和初始化
#include <iostream>
#include <list>
int main() {
std::list<int> lst1; // 空的list
std::list<int> lst2(5); // 包含5个默认初始化元素的list
std::list<int> lst3(5, 10); // 包含5个元素,每个元素为10
std::list<int> lst4 = {1, 2, 3, 4}; // 使用初始化列表
return 0;
}
常用函数
push_back(const T& val) //在链表末尾添加元素
push_front(const T& val) //在链表头部添加元素
pop_back() //删除链表末尾的元素
pop_front() //删除链表头部的元素
insert(iterator pos, val) //在指定位置插入元素
erase(iterator pos) //删除指定位置的元素
clear() //清空所有元素
size() //返回链表中的元素数量
empty() //检查链表是否为空
front() //返回链表第一个元素
back() //返回链表最后一个元素
remove(const T& val) //删除所有等于指定值的元素
sort() //对链表中的元素进行排序
merge(list& other) / /合并另一个已排序的链表
reverse() //反转链表
begin() //返回链表的起始迭代器
end() //返回链表的终点迭代器
模拟实现
首先我们要用模板函数先定义一个节点的结构和构造函数
template<class T>
struct list_node
{
T _data;
list_node<T>* _next;
list_node<T>* _prev;
list_node(const T& data = T())
:_data(data)
, _next(nullptr)
, _prev(nullptr)
{}
};
之后我们使用模板函数定义链表的迭代器
要实现++,--,==等运算符的重载
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* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self& operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s) const
{
return _node == s._node;
}
};
最后我们用模板函数再设计一下链表
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;
iterator begin()
{
return _head->_next;
}
iterator end()
{
return _head;
}
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;
}
void empty_init()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
list()
{
empty_init();
}
list(initializer_list<T> il)
{
empty_init();
for (auto& e : il)
{
push_back(e);
}
}
// lt2(lt1)
list(const list<T>& lt)
{
empty_init();
for (auto& e : lt)
{
push_back(e);
}
}
// lt1 = lt3
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
auto it = begin();
while (it != end())
{
it = erase(it);
}
}
void swap(list<T>& lt)
{
std::swap(_head, lt._head);
std::swap(_size, lt._size);
}
void push_back(const T& x)
{
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(x);
//结构为prev newnode cur
newnode->_next = cur;
cur->_prev = newnode;
newnode->_prev = prev;
prev->_next = newnode;
++_size;
return newnode;
}
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
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;
--_size;
return next;
}
size_t size() const
{
return _size;
}
bool empty() const
{
return _size == 0;
}
private:
Node* _head;
size_t _size;
};