此处是带头双向链表
对于List,不像string、vector之类的,没有reserve的说法,也不支持[ ]和下标,只有一种方式遍历List也就是采用迭代器(范围for的底层也是迭代器)。
insert函数和erase函数(需要配合std库里面的find函数)
If no elements match, the function returns last.
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
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迭代器
// 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封装
成员变量
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()函数
iterator begin()
{return iterator(_head->_next);
}const_iterator begin() const
{return const_iterator(_head->_next);
}
end()函数
iterator end()
{return iterator(_head);
}
const_iterator end() const
{return const_iterator(_head);
}
默认构造函数和empty_init()函数
void empty_init()
{_head = new node;_head->_next = _head;//自己的next指向自己_head->_prev = _head;
}list()
{empty_init();
}
析构函数和clear()函数
void clear()
{iterator it = begin();while (it != end()){erase(it++);//}
}
迭代器构造函数
template <class Iterator>
list(Iterator first, Iterator last)
{empty_init();while (first != last){push_back(*first);//*first返回的是_node->_data;++first;}
}
拷贝构造
//传统写法
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函数
void swap(list<T>& tmp)
{std::swap(_head, tmp._head);
}
赋值运算符重载
list<T>& operator=(list<T> lt)//这里采用传值传参,形参是实参的一个拷贝
{swap(lt);return *this;
}
push_back()函数和push_front()函数
void push_back(const T& x)
{insert(end(), x);
}
void push_front(const T& x)
{insert(begin(), x);
}
pop_back()函数和pop_front()函数
void pop_back()
{erase(--end());
}
void pop_front()
{erase(begin());
}
insert()函数 Key
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
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);
}