您的位置:首页 > 其它

STL--set注意事项

2015-11-24 20:09 483 查看
混杂着记录的,可能会比较乱,但是都是一些有用的点

1.insert

pair<iterator, bool> insert(const value_type& x);
iterator insert(iterator position, const value_type& x);


单参数的insert: The first version return a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element that already had its same value in the set. The pair::second element in the pair is set to true if a
new element was inserted or false if an element with the same value existed.

双参数的insert: The second version returns an iterator pointing to either the newly inserted element or to the element that already had its same value in the set.

双参数insert允许对x将要插入的位置的线索说明。如果线索给的精确,那么插入会很快。如果不精确的话就需要用常规的插入算法来完成,此时与单参数的insert相同。

set<int> iSet1, iSet2;

for (int i = 0; i < 100000; ++i)
iSet1.insert(i);

for (int i = 0; i < 100000; ++i)
iSet2.insert(iSet2.end(), i);


单参数的耗时1856毫秒,双参数的耗时920毫秒,正确使用insert可以减少插入的时间。

2.set的第二个模板参数

默认情况下,排序操作使用less<Object>函数对象实现,而该函数对象是通过对Object调用operator<来实现的

比如判断相等:!(isLessThan(lhs, rhs) || isLessThan(rhs, lhs)) 

例如可以生成一个存储string对象的set,通过使用CaseInsensitiveCompare函数对象来忽略字符的大小写

class CaseInsensitiveCompare {
public:
bool operator()(const string& lhs, const string& rhs) {
return stricmp(lhs.c_str(), rhs.c_str()) < 0;
}
};

int main()
{
set<string, CaseInsensitiveCompare> s;

s.insert("hello");
s.insert("HellO");

cout << s.size(); // 1

return 0;
}
3.排序准则
⑴以template参数定义之

例如 std::set<int, std::greater<int> > coll;

这种情况下排序准则就是型别的一部分,因此型别系统确保“只有排序准则相同的容器才能被合并”。实际的排序准则是容器所产生的函数对象(functor,仿函数)。

class Person {
public:
string firstname()const;
string lastname()const;
};
class PersonSortCriterion {
public:
bool operator()(const Person& p1, const Person& p2)const {
/**
* p1的姓小于p2的姓
* 当姓相等时候p1的名字小于p2的名字
*/
return p1.lastname() < p2.lastname() ||
((!(p2.lastname() < p1.lastname())) && p1.firstname() < p2.firstname());
}
};

int main()
{
typedef set<Person, PersonSortCriterion> PersonSet;

PersonSet coll;

PersonSet::iterator pos;
for (pos = coll.begin(); pos != coll.end(); ++pos) {
// ...
}

return 0;
}
这个就是仿函数,用类的operator()取代一般函数,一般函数无法做到成为一个类别。所以可以用仿函数来当set的template参数。

在coll的构造函数内会自动生成class PersonSortCriterion的一个实体,所有的元素都将以此为排序准则进行排序。

你无法将这个set拿来和“拥有不同排序准则”的其他set合并或互相赋值。

⑵以构造函数参数定义之。

这种情况下,同一个型别可以运用不同的排序准则,而排序准则的初始值或状态也可以不同。

如果执行期才获得排序准则,而且需要用到不同的排序准则(但数据型别必须相同),这个方法可以派上用场。

// type for sorting criterion
template <class T>
class RuntimeCmp {
public:
enum cmp_mode{ normal, reverse };
private:
cmp_mode mode;
public:
// constructor for sorting criterion
// - default criterion uses value normal
RuntimeCmp(cmp_mode m = normal) :mode(m) {}
// comparison of elements
bool operator()(const T& t1, const T& t2)const {
return mode == normal ? t1 < t2 : t2 < t1;
}
// comparison of sorting criteria
bool operator==(const RuntimeCmp& rc) {
return mode == rc.mode;
}
};

typedef set<int, RuntimeCmp<int> > IntSet;
void fill(IntSet& set);

int main()
{
// create, fill, and print set with normal element order
// - uses default sorting criterion
IntSet coll1;
fill(coll1);
PRINT_ELEMENT(coll1, "coll1: ");	// 1 2 4 5 6 7

// create sorting criterion with reverse element order
RuntimeCmp<int> reverse_order(RuntimeCmp<int>::reverse);

// create, fill, and print set with reverse element order
IntSet coll2(reverse_order);
fill(coll2);
PRINT_ELEMENT(coll2, "coll2: ");	// 7 6 5 4 2 1

// assign elements AND sorting criterion
coll1 = coll2;
PRINT_ELEMENT(coll1, "coll1: ");	// 7 6 5 4 2 1
coll1.insert(3);
PRINT_ELEMENT(coll1, "coll1: ");	// 7 6 5 4 3 2 1

// just to make sure...
if (coll1.value_comp() == coll2.value_comp()) {	// true
cout << "coll1 and coll2 have same sorting criterion" << endl;
}
else {
cout << "coll1 and coll2 have different sorting criterion" << endl;
}

return 0;
}

void fill(IntSet& set) {
// fill insert elements in random order
set.insert(4);
set.insert(7);
set.insert(5);
set.insert(1);
set.insert(6);
set.insert(2);
set.insert(5);
}
这个例子说明了如果准则不同,准则本身也会被赋值(assigned)或交换(swapped)。

4.迭代器性质

和其他所有关联式容器类似,这里的迭代器是双向迭代器(bidirectional iterator)。

所以对于只能用于随机存取迭代器(random access iterator)的STL算法(例如排序或随机乱序random_shuffling),set和multiset就用不了了。

更重要的是,对迭代器操作而言,所有元素都被视为常数。set<int> iter = iSet.begin(); *iter = 1; // Error:不可修改的左值

这可以确保你不会人为改变元素值,从而打乱既定顺序。然而也使得你无法对sets或multisets元素调用任何变动性算法(modifying algorithms)

例如你不能对它调用remove(),因为remove()算法实际上是一个参数值覆盖被移除的元素,如果要移除set和multisets的元素,你只能使用它们所提供的成员函数。

c

co

Com

Comp

Compa

Compar

compari

comparis

comparis

compariso

comparison
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: