目录
本节分析list的插入删除重载等源码
push和pop操作
注意list是一个双向循环链表
push都调用insert() pop都调用erase()
template <class T, class Alloc = alloc>
class list
{
...
// 直接在头部或尾部插入
void push_front(const T& x) { insert(begin(), x); }
void push_back(const T& x) { insert(end(), x); }
// 直接在头部或尾部删除
void pop_front() { erase(begin()); }
void pop_back() {
iterator tmp = end();
erase(--tmp);
}
...
};
删除
template <class T, class Alloc = alloc>
class list
{
...
iterator erase(iterator first, iterator last);
void clear();
// 参数是一个迭代器
// 修改该元素的前后指针指向再单独释放节点就行了
iterator erase(iterator position) {
link_type next_node = link_type(position.node->next);
link_type prev_node = link_type(position.node->prev);
prev_node->next = next_node;
next_node->prev = prev_node;
destroy_node(position.node);
return iterator(next_node);
}
...
};
// erase的重载, 删除两个迭代器之间的元素
template <class T, class Alloc>
list<T,Alloc>::iterator list<T, Alloc>::erase(iterator first, iterator last)
{
// 就是一次次调用erase进行删除
while (first != last)
erase(first++);
return last;
}
// remove调用erase链表清除
template <class T, class Alloc>
void list<T, Alloc>::remove(const T& value) {
iterator first = begin();
iterator last = end();
while (first != last) {
iterator next = first;
++next;
if (*first == value) erase(first);
first = next;
}
}
clear函数是删除除了空节点之外的所有结点
// 删除除空节点以外的所有节点
template <class T, class Alloc>
void list<T, Alloc>::clear()
{
link_type cur = (link_type) node->next;
// 除空节点都删除
while (cur != node) {
link_type tmp = cur;
cur = (link_type) cur->next;
destroy_node(tmp);
}
node->next = node;
node->prev = node;
}
重载
// 判断两个list相等
template <class T, class Alloc>
inline bool operator==(const list<T,Alloc>& x, const list<T,Alloc>& y)
{
typedef typename list<T,Alloc>::link_type link_type;
link_type e1 = x.node;
link_type e2 = y.node;
link_type n1 = (link_type) e1->next;
link_type n2 = (link_type) e2->next;
// 将两个链表执行一一的对比来分析是否相等.
// 这里不把元素个数进行一次比较, 主要获取个数时也要遍历整个数组, 所以就不将个数纳入比较
for ( ; n1 != e1 && n2 != e2 ; n1 = (link_type) n1->next, n2 = (link_type) n2->next)
if (n1->data != n2->data)
return false;
return n1 == e1 && n2 == e2;
}
template <class T, class Alloc>
inline bool operator<(const list<T, Alloc>& x, const list<T, Alloc>& y) {
return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
template <class T, class Alloc>
list<T, Alloc>& list<T, Alloc>::operator=(const list<T, Alloc>& x) {
if (this != &x) {
iterator first1 = begin();
iterator last1 = end();
const_iterator first2 = x.begin();
const_iterator last2 = x.end();
// 直到两个链表有一个空间用尽
while (first1 != last1 && first2 != last2)
*first1++ = *first2++;
// 原链表大, 复制完后要删除掉原链表多余的元素
if (first2 == last2)
erase(first1, last1);
// 原链表小, 复制完后要还要将x链表的剩余元素以插入的方式插入到原链表中
else
insert(last1, first2, last2);
}
return *this;
}
template <class T, class Alloc = alloc>
class list
{
...
resize(size_type new_size, const T& x);
void resize(size_type new_size) { resize(new_size, T()); }
...
};
template <class T, class Alloc>
void list<T, Alloc>::resize(size_type new_size, const T& x)
{
iterator i = begin();
size_type len = 0;
for ( ; i != end() && len < new_size; ++i, ++len)
;
// 如果链表长度大于new_size的大小, 那就删除后面多余的节点
if (len == new_size)
erase(i, end());
// i == end(), 扩大链表的节点
else
insert(end(), new_size - len, x);
}
unique
相同的元素只保留一个副本
template <class T, class Alloc> template <class BinaryPredicate>
void list<T, Alloc>::unique(BinaryPredicate binary_pred) {
iterator first = begin();
iterator last = end();
if (first == last) return;
iterator next = first;
// 删除连续相同的元素, 留一个副本
while (++next != last) {
if (binary_pred(*first, *next))
erase(next);
else
first = next;
next = first;
}
}
insert
注意:insert是将元素插入到指定地址的前一个位置
template <class T, class Alloc = alloc>
class list
{
...
public:
// 最基本的insert操作, 之插入一个元素
iterator insert(iterator position, const T& x)
{
// 将元素插入指定位置的前一个地址
link_type tmp = create_node(x);
tmp->next = position.node;
tmp->prev = position.node->prev;
(link_type(position.node->prev))->next = tmp;
position.node->prev = tmp;
return tmp;
}
// 以下重载函数都是调用iterator insert(iterator position, const T& x)函数
iterator insert(iterator position) { return insert(position, T()); }
#ifdef __STL_MEMBER_TEMPLATES
template <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last);
#else /* __STL_MEMBER_TEMPLATES */
void insert(iterator position, const T* first, const T* last);
void insert(iterator position,
const_iterator first, const_iterator last);
#endif /* __STL_MEMBER_TEMPLATES */
void insert(iterator pos, size_type n, const T& x);
void insert(iterator pos, int n, const T& x) {
insert(pos, (size_type)n, x);
}
void insert(iterator pos, long n, const T& x) {
insert(pos, (size_type)n, x);
}
void resize(size_type new_size, const T& x);
...
};
#ifdef __STL_MEMBER_TEMPLATES
template <class T, class Alloc> template <class InputIterator>
void list<T, Alloc>::insert(iterator position, InputIterator first, InputIterator last)
{
for ( ; first != last; ++first)
insert(position, *first);
}
#else /* __STL_MEMBER_TEMPLATES */
template <class T, class Alloc>
void list<T, Alloc>::insert(iterator position, const T* first, const T* last) {
for ( ; first != last; ++first)
insert(position, *first);
}
template <class T, class Alloc>
void list<T, Alloc>::insert(iterator position,
const_iterator first, const_iterator last) {
for ( ; first != last; ++first)
insert(position, *first);
}
#endif /* __STL_MEMBER_TEMPLATES */
template <class T, class Alloc>
void list<T, Alloc>::insert(iterator position, size_type n, const T& x) {
for ( ; n > 0; --n)
insert(position, x);
}