SGISTL源码阅读十三 list容器下
前言
我们将继续介绍list
的相关操作
深入源码
remove
remove
的作用是删除指定值的节点
template <class T, class Alloc>
void list<T, Alloc>::remove(const T& value) {
iterator first = begin();
iterator last = end();
//遍历list
while (first != last) {
iterator next = first;
++next;
//如果当前节点的value为指定值,则删除它
if (*first == value) erase(first);
first = next;
}
}
unique()
该函数的作用是删除值相同的连续的元素,直至该元素剩最后一个。
template <class T, class Alloc>
void list<T, Alloc>::unique() {
iterator first = begin();
iterator last = end();
if (first == last) return;
iterator next = first;
while (++next != last) {
/* 比较前后两个元素的值
* 若相等,则进行删除
* 否则移动first迭代器,跟进到next
*/
if (*first == *next)
erase(next);
else
first = next;
/* 可能会因为erase删除操作使next失效
* 所以需要更新next,保持与first指向相同元素
*/
next = first;
}
}
merge
函数的作用是将list x合并到该list上,合并的顺序是递增排序,并且要求合并前,两个list中的元素已经是递增的。调用了前面提到过的transfer
函数
template <class T, class Alloc>
void list<T, Alloc>::merge(list<T, Alloc>& x) {
iterator first1 = begin();
iterator last1 = end();
iterator first2 = x.begin();
iterator last2 = x.end();
//两个链表还没到结尾
while (first1 != last1 && first2 != last2)
/* 若*first2 < *first1
* 则将first2指向的元素移动到first1指向的元素前面
* 否则first1++,寻找下一个插入点
*/
if (*first2 < *first1) {
iterator next = first2;
transfer(first1, first2, ++next);
first2 = next;
}
else
++first1;
/* 若first2 != last2
* 证明x的元素还没全部被移动到list上
* 将剩余的元素移动到last1前面
*/
if (first2 != last2) transfer(last1, first2, last2);
}
reverse
故名思意,这个函数的作用是将链表倒置
template <class T, class Alloc>
void list<T, Alloc>::reverse() {
//如果链表为空或者只有一个节点,则不用做任何操作
if (node->next == node || link_type(node->next)->next == node) return;
iterator first = begin();
++first;
while (first != end()) {
iterator old = first;
++first;
//利用前插法倒置,begin位置不动,把依次后面的元素插入到begin前面去
//插入结束后begin的位置是最后一个节点
transfer(begin(), old, first);
}
}
操作符重载
//重载=
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++;
//如果list比listx元素多,那么删除list中多余元素
if (first2 == last2)
erase(first1, last1);
//如果list中空间不够,则使用插入
else
insert(last1, first2, last2);
}
return *this;
}
//重载==
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)
//如果value不同直接返回false
if (n1->data != n2->data)
return false;
//若最后长度相等,就返回true,否则返回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());
}
总结
我们继续对list
相关操作进行了分析。
对list
的学习就到此结束了,接下来将继续学习deque