常数范围内
在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代
。list(){
//带头双向循环
_head = new Node(T()); //这里的构造不能传0,因此这里不一定是int类型的,这里T可能是vector,也可能是string对象
_head->_next = _head;
_head->_prev = _head;
}
list(const list<T>& lt){
//深拷贝
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
for(const auto& e : lt){
push_back(e);
}
}
template<class InputIterator>
list(InputIterator first,InputIterator last){ //这里不仅仅支持链表的初始化,而且还支持string或者vector的迭代器
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
while(first != last){
push_back(*first);
++first;
}
}
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 的迭代器
迭代器有两种实现方式,具体应根据容器底层数据结构实现:
方法:
这里typdef的__list_iterator里带了三个参,其中第二和第三个类模版分别用于决定operator*()返回什么样类型的的对象 和 用于operator->()返回当前节点的数据
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 iterator(_head->_next);
}
iterator end(){
return iterator(_head);
}
const_iterator begin() const{
return const_iterator(_head->_next);
}
const_iterator end() const {
return const_iterator(_head);
}
private:
Node* _head;
};
//解引用
Ref operator*(){
return _node->_data;
}
Ptr operator->(){
return &_node->_data;
}
// ++it
self& operator++(){
_node = _node->_next;
return *this;
}
// it++
self operator++(int){ //后置++
self tmp(*this);
_node = _node->_next;
return tmp;
}
// --it
self& operator--(){
_node = _node->_prev;
return *this;
}
// it--
self operator--(int){ //后置--
self tmp(*this);
_node = _node->_prev;
return tmp;
}
//比较是否相等
bool operator!=(const self& it){
return _node != it._node;
}
bool operator==(const self& it){
return _node == it._node;
}
遍历一遍,直到遇到带头后结束
size_t size(){
size_t n = 0;
iterator it = begin();
while(it != end()){
++it;
++n;
}
return n;
}
bool empty(){
return begin() == end();
}
iterator insert(iterator pos, const T& x){
Node* cur = pos._node; //当前节点
Node* prev = cur->_prev;
Node* newnode = new Node(x);
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return iterator(newnode); //反回新插入节点
}
void push_back(const T& x){
insert(end(), x)
}
void push_front(const T& x){
insert(begin(), x);
}
由于list数据结构的特点决定了不能像数组一样实现O(1)访问任意节点,所以标准库里只提供了头删和尾删
iterator erase(iterator pos){
assert(pos != end());
Node* cur = pos._node;
Node* pre = cur->_prev;
Node* next = cur->_next;
delete cur;
pre->_next = next;
next->_prev = prev;
return iterator(next);
}
void pop_back(){
erase(--end());
}
void pop_front(){
erase(begin());
}
这里需要注意的是只有当实例化对象开辟了空间后才析构,否则进入clear函数后会报错
void clear(){
iterator it = begin();
while(it != end()){
it = erase(it);
}
~list(){
clear();
delete _head;
_head = nullptr;
}
Gitee链接
List simulation
创作不易,如果文章对你帮助的话,点赞三连哦:)