Effective STL 读书笔记 6
来源:互联网 发布:java正则表达式匹配url 编辑:程序博客网 时间:2024/05/17 02:33
Item 30:在应用算法时,确定目标范围(destination ranges)足够大。
Item 31:了解 sort 的选项,你并不总是需要全排序。
Item 32:在 remove 后紧跟 erase 确保元素被删除。
Item 33:当心在指针容器上调用的 remove 算法。
Item 34:注意,有些算法需要 sorted ranges。
- 首先以下代码是错误的,transform 将对 dest.end() 开始的 N 个元素调用赋值操作,但这些元素并不存在:
transform(src.begin(), src.end(),
dest.end(),
transmogrify);
dest.end(),
transmogrify);
- 正确的方法是先创建对象(push_back),再赋值,如下:
transform(src.begin(), src.end(),
back_inserter(dest), // or front_inserter(dest),
transmogrify);
back_inserter(dest), // or front_inserter(dest),
transmogrify);
- 如果想在任意位置插入对象:
transform(src.begin(), src.end(),
inserter(dest, dest.begin() + dest.size() / 2), // at middle
transmogrify);
inserter(dest, dest.begin() + dest.size() / 2), // at middle
transmogrify);
- 上面代码在处理 string 和 vector 容器时,效率较低,可以遵照 Item 14 的方法使用 reserve:
dest.reserve(dest.size() + src.size());
transform(src.begin(), src.end(),
back_inserter(dest),
transmogrify);
transform(src.begin(), src.end(),
back_inserter(dest),
transmogrify);
- 注意即使你已经使用了 reserve 创造了足够的空间,但并不能省去 inserter 的调用,因为 reserve 创造的仅仅是空间,而没有构造对象,而 transform 函数是针对已存在的对象调用赋值操作。
- 如果并不许要插入对象而仅仅是改变(overwrite)容器内的值,可以使用:
dest.resize(src.size());
transform(src.begin(), src.end(),
dest.begin(),
transmogrify);
transform(src.begin(), src.end(),
dest.begin(),
transmogrify);
- 或者:
dest.clear();
dest.reserve(src.size());
transform(src.begin(), src.end(),
back_inserter(dest);
transmogrify);
dest.reserve(src.size());
transform(src.begin(), src.end(),
back_inserter(dest);
transmogrify);
- 在调用算法时,必须确定该算法所需要的空间足够,空间是否会随着算法自动增加。增加空间的方法是调用 insert iterators,包括 ostream_iterator 及上面的 back_inserter, front_inserter, inserter。
Item 31:了解 sort 的选项,你并不总是需要全排序。
- 我们要排序,但并不总是需要全排序,有时我们仅仅需要 Top 10,有时我们只关心 Sub Contents,对这些需求作全排序太浪费计算资源,本条目介绍了几种 sub sort 算法。
- partial_sort 可以看作是 Top N 算法,将最小容器中最小的 N 个元素按升序排列在容器头部。
- nth_element 和上面的算法接近,将最小的 N 个元素放在容器头部,但并没有对它们排序。
- 上面两个排序算法都是非 stable 的,一个 stable 的排序算法不会改变两个相等(等价)对象的顺序(排序之前的顺序)。STL 中提供了一个 stable 的排序算法:stable_sort。
- nth_element 还可以用作查找目标容器内排序后的某个特殊值,就像其名字“第 n 个元素”:
vector<int> data;
...
vector<int>::iterator goal = data.begin() + 5;
nth_element(data.begin(), goal, data.end(), my_data_compare);
...
vector<int>::iterator goal = data.begin() + 5;
nth_element(data.begin(), goal, data.end(), my_data_compare);
- 上面代码执行完后 goal 指向的对象是容器中第 5 小的元素。
- partition 用来将容器内的元素按照指定的规则分成两部分,函数的返回值为分界线。与上面算法不同的是不需要指定个数 N,仅仅指定划分规则。
- stable_partition 与上相同,但并不改变相同元素的原有顺序。
- 按照性能排序:
- partition
- stable_partition
- nth_element
- partial_sort
- sort
- stable_sort
Item 32:在 remove 后紧跟 erase 确保元素被删除。
- 首先 remove 不能够删除任何元素,因为其参数中没有容器本身,只有迭代器。除了 list::remove,因为是成员函数所以有能力删除元素。
- remove 算法仅仅是用 unremoved 的元素来覆盖 removed 的元素,然后返回 middle。从 begin 到 middle 间的元素是未被删除的,而 middle 到 end 间的元素并没有任何改变。(但也已经没有任何用处)。即 [1, 2, 3, 99, 5, 99, 7, 8, 9, 99] 被 remove(99) 后变成 [1, 2, 3, 5, 7, 8, 9, 8, 9, 99],红色部分为未改变部分。
- 应该用如下方法删除元素:
vector<int> v;
...
v.erase(remove(v.begin(), v.end(), 99), v.end());
...
v.erase(remove(v.begin(), v.end(), 99), v.end());
- remove 类的算法还有:remove_if 和 unique
Item 33:当心在指针容器上调用的 remove 算法。
- remove 覆盖而不删除,如果容器存储的是指针,为防止资源泄露,应尽量避免使用 remove 类的算法。考虑用 partition 代替。
- 如必须要使用:
void deleteAndNullifyUncertified(Object *& obj) {
if (!obj->isCertified()) {
delete obj;
obj = 0;
}
}
for_each(v.begin(), v.end(), deleteAndNullifyUncertified);
v.erase(remove(v.begin(), v.end(),
static_cast<Object *>(0)),
v.end());
if (!obj->isCertified()) {
delete obj;
obj = 0;
}
}
for_each(v.begin(), v.end(), deleteAndNullifyUncertified);
v.erase(remove(v.begin(), v.end(),
static_cast<Object *>(0)),
v.end());
- 也可以用 smart_point 来代替原始指针存入容器。(smart_point 可以参考 boost)
Item 34:注意,有些算法需要 sorted ranges。
- 以下算法需要 sorted ranges:
binary_search
lower_bound
upper_bound
equal_range
set_union
set_intersection
set_difference
set_symmetric_difference
merge // get two sorted range, return a merged sorted range.
inplace_merge
includes // whether a range is include another.
lower_bound
upper_bound
equal_range
set_union
set_intersection
set_difference
set_symmetric_difference
merge // get two sorted range, return a merged sorted range.
inplace_merge
includes // whether a range is include another.
- 以下算法一般用在 sorted ranges 上,但并不是必须。
unique
unique_copy
unique_copy
- unique 将同一相等组内的对象只保留一个。例如:[1,2,1,3,3,3,1] --> [1,2,1,3,1,3,1],红色为需要 erase 的部分,其中 1 虽然出现了多次但并不在一个“相等组”内。
- 注意,在调用这些算法的时候所使用的比较函数(对象)必须与排序算法使用的相同!
- Effective STL 读书笔记 6
- effective stl读书笔记 -- Item 6
- effective stl读书笔记 —— Item 6
- 《Effective STL》读书笔记四:Item 6 - 9
- Effective STL 读书笔记 1
- Effective STL 读书笔记 2
- Effective STL 读书笔记 3
- Effective STL 读书笔记 4
- Effective STL 读书笔记 5
- Effective STL 读书笔记 7
- Effective STL 读书笔记 8
- Effective STL 读书笔记 9
- effective stl 读书笔记
- effective STL 读书笔记 二
- 读书笔记 Effective STL
- 《Effective STL》读书笔记
- 《Effective STL》读书笔记
- effective STL读书笔记
- Castle ActiveRecord 学习 123
- UK to pioneer download-to-own movies
- 数据库范式
- 小技巧
- Microsoft Visual C++ 与 MinGW,附图
- Effective STL 读书笔记 6
- 《COM原理及应用》学习笔记之写在前面的话
- 《COM原理及应用》学习笔记之第一章
- 《COM原理及应用》学习笔记之第二章
- xml数据岛中添加记录
- e words
- 看到了一篇文章
- C++/CLI 中字符串类型的转化: 把System::String转化为std::string
- 用C#建立通用对象池[3]