c++ stl set
2013-07-21 08:45
218 查看
虽然经常使用c++的stl,set也是经常使用的一个容器,但是发现对于set的理解还是比较浅显。今天使用时无意就撞入了一个坑里。
stl中set和map都是用红黑树实现的。set是key和value相同的结构。
代码如下:
[/code]
执行结果中两个问题:
第一:输出的set的顺序不对。
第二:find结果不对。 3,key3 是存在的而find为false
仔细看了set的说明才弄明白。参见后面构造函数部分
[/code]
set 初始化为:set obj_set; 别的相同
同时需要注意:该函数的要求:向set中添加的元素类型必须重载<操作符用来排序。排序满足以下准则:
1、非对称,若A<B为真,则B<A为假。
2、可传递,若A<B,B<C,则A<C。
3、A<A永远为假。
set中判断元素是否相等:
if(!(A<B || B<A)),当A<B和B<A都为假时,它们相等。
而注意上面我们使用的为string的compare函数,而我们看下该函数的声明:
string (1)
substrings (2)
c-string (3)
buffer (4)
该方法返回的是一个pair,可以使用insert(xxx).second 来判断插入是否成功
with hint (2) iterator insert (iterator position, const value_type& val);
查看函数说明:
The function optimizes its insertion time if position points to the element that will precede the inserted element.
Notice that this is just a hint and does not force the new element to be inserted at that position within theset container (the elements in a set always follow a specific order).
Member types iterator and const_iterator are defined in map as a bidirectional iterator type that point to elements.
即:如果提供的position是带插入元素之前的节点,那么可以提升插入的效率。但是这只是一个提示(需要保证set的顺序)
返回的iterator 指向插入节点所在的位置(如果元素已经存则插入失败,iterator指向set中已经存在的元素的位置)。
range (3) template <class InputIterator> void insert (InputIterator first, InputIterator last);
插入多个元素的结构。返回是void类型。
从set中移除元素。通过看erase的说明。erase时,移除元素对应的迭代器会失效。set中其他元素的指针和迭代器仍然有效。
对于set遍历移除时,可以使用 set.erase(it++);的方式。
refer:http://www.cplusplus.com/reference/set/set/
refer:http://www.cplusplus.com/reference/string/string/compare/
stl中set和map都是用红黑树实现的。set是key和value相同的结构。
代码如下:
[code] #include <set>
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
typedef struct Object {
Object(int t, string k) : timestamp(t), key(k) {
}
int timestamp;
string key;
bool operator <(const Object& o) const {
return key.compare(o.key);
}
}Object;
ostream& operator<<(ostream& os, const Object& obj) {
os << "(" << obj.timestamp << ":" << obj.key << ")";
}
bool Compare(const string& s1, const string& s2) {
return s1.compare(s2);
}
int main(int argc, char** argv) {
{
set<Object> obj_set;
cout << "insert (1, key1) : " << obj_set.insert(Object(1, "key1")).second << endl;
cout << "insert (2, key1) : " << obj_set.insert(Object(2, "key1")).second << endl;
cout << "insert (5, key5) : " << obj_set.insert(Object(5, "key5")).second << endl;
cout << "insert (3, key3) : " << obj_set.insert(Object(3, "key3")).second << endl;
cout << "insert (4, key7) : " << obj_set.insert(Object(4, "key7")).second << endl;
cout << "insert (4, key6) : " << obj_set.insert(Object(4, "key6")).second << endl;
cout << "insert (4, key9) : " << obj_set.insert(Object(4, "key9")).second << endl;
cout << "insert (4, key8) : " << obj_set.insert(Object(4, "key8")).second << endl;
copy(obj_set.begin(), obj_set.end(), std::ostream_iterator<Object>(std::cout, " "));
cout << endl;
cout << "obj_set.find(Object(1, key1)) : " << (obj_set.find(Object(1, "key1")) != obj_set.end()) << endl;
cout << "obj_set.find(Object(1, key1)) : " << (obj_set.find(Object(1, "key1")) != obj_set.end()) << endl;
cout << "obj_set.find(Object(3, key3)) : " << (obj_set.find(Object(3, "key3")) != obj_set.end()) << endl;
cout << "obj_set.find(Object(2, key4)) : " << (obj_set.find(Object(2, "key4")) != obj_set.end()) << endl;
}
return 0;
}
[/code]
执行结果如下:
第一:输出的set的顺序不对。
第二:find结果不对。 3,key3 是存在的而find为false
仔细看了set的说明才弄明白。参见后面构造函数部分
set的构造函数:
template < class T, // set::key_type/value_type class Compare = less<T>, // set::key_compare/value_compare class Alloc = allocator<T> > // set::allocator_type > class set;
从set的构造函数看出,其需要一个比较函数,默认使用的less比较函数。
通常set中存放一些int、string等类型的数据时,使用默认的通常不会有什么问题。
而如果是我们自定义的一些结构体的时候,则需要为其提供比较函数的实现。
比较函数实现有两种范式:
一:该结构体是你自己设计的,则那么在类中重载operator<就可以了,需要注意的就是必须将其设计为const成员函数
如上面为:bool operator <(const Object& o) const;
注意必须为const成员函数
二: 该结构体是别人设计的,类中没有重载operator<,而且你也没有办法去修改别人的代码。那么你就需要再外部设计一个比较器。
[code] class ObjCompare {
public:
bool operator()(const Object& o1, const Object& o2) {
return o1.key.compare(o2.key);
}
};
[/code]
set 初始化为:set obj_set; 别的相同
同时需要注意:该函数的要求:向set中添加的元素类型必须重载<操作符用来排序。排序满足以下准则:
1、非对称,若A<B为真,则B<A为假。
2、可传递,若A<B,B<C,则A<C。
3、A<A永远为假。
set中判断元素是否相等:
if(!(A<B || B<A)),当A<B和B<A都为假时,它们相等。
而注意上面我们使用的为string的compare函数,而我们看下该函数的声明:
string (1)
int compare (const string& str) const;
substrings (2)
int compare (size_t pos, size_t len, const string& str) const; int compare (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;
c-string (3)
int compare (const char* s) const; int compare (size_t pos, size_t len, const char* s) const;
buffer (4)
int compare (size_t pos, size_t len, const char* s, size_t n) const;
注意函数的返回值为int,
这时就明白了,上面我们实现的比较函数。当二者相等时返回0,为false, 而当不等时,则返回值或者为1或者为-1,都是true,是不满足set的排序函数的要求的。
我们修改下比较函数为:
执行结果为:
此时可以看出set是按照key有序的。同时find的结果也是正确的。
(注意[2,key1] 的find结果为1是正确的,因为我们的比较函数是针对key的,不对timestamp比较)
insert方法
single element (1) pair<iterator,bool> insert (const value_type& val);该方法返回的是一个pair,可以使用insert(xxx).second 来判断插入是否成功
with hint (2) iterator insert (iterator position, const value_type& val);
查看函数说明:
The function optimizes its insertion time if position points to the element that will precede the inserted element.
Notice that this is just a hint and does not force the new element to be inserted at that position within theset container (the elements in a set always follow a specific order).
Member types iterator and const_iterator are defined in map as a bidirectional iterator type that point to elements.
即:如果提供的position是带插入元素之前的节点,那么可以提升插入的效率。但是这只是一个提示(需要保证set的顺序)
返回的iterator 指向插入节点所在的位置(如果元素已经存则插入失败,iterator指向set中已经存在的元素的位置)。
range (3) template <class InputIterator> void insert (InputIterator first, InputIterator last);
插入多个元素的结构。返回是void类型。
erase方法
从set中移除元素。通过看erase的说明。erase时,移除元素对应的迭代器会失效。set中其他元素的指针和迭代器仍然有效。
对于set遍历移除时,可以使用 set.erase(it++);的方式。
refer:http://www.cplusplus.com/reference/set/set/
refer:http://www.cplusplus.com/reference/string/string/compare/
相关文章推荐
- C++_STL_set
- c++STL容器(map,set,vector,stack,queue)
- 【学习笔记】C++高级程序设计:STL:Set 和 Multiset
- C++_STL—Set及Multiset篇
- c++的stl中的set/multiset
- <C++ STL set>集合并,交,差,对称差总结
- C++ STL之set常用指令
- C++ STL学习——set
- C++STL(vector,map,set,list)成员函数整理
- C++STL中set的使用策略(详解)
- 【C++ STL】细数C++ STL 的那些事---set(元素唯一,且排序)
- sdut 2159 Ivan comes again! C++ STL set
- 【C++】STL常用容器总结之九:集合set
- C++学习 STL之set使用方法小结
- c++ STL 算法set_union和sort
- 细数C++ STL 的那些事---set(元素唯一,且排序)
- C++ 标准模板库STL set 使用方法与应用介绍(一)
- C++与STL入门--set
- 标准模板库 STL-2 编程题#3:Set(Coursera 程序设计与算法 专项课程3 C++程序设计;执行输入的命令和数据)
- c++ stl set