STL学习笔记之容器--set
2015-06-16 15:19
246 查看
set集合容器使用一种称为红黑树(Red-Black Tree) 的平衡二叉检索树的数据结构,来组织泛化的元素数据。每个节点包含一个取值红色或黑色的颜色域,以利于进行树的平衡处理。作为节点键值的元素的插入,必须确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值。不会将重复的键值插入容器,也不需要指定具体的插入位置,而按元素在树中的关联关系,进行位置检索和插入,元素的删除亦然。
元素数据的检索,使用的是二叉检索树的中序遍历算法,检索的效率高于 vector 、 deque 和 lsit 等容器。由于采用中序遍历算法可将二叉检索树的键值,由小到大排列遍历出来,因此 set 集合容器蕴含了元素间的有序性。
作为一种关联容器,set 集合容器实现了 Unique Sorted Associative Container 和 Simple Associative Container 概念的函数定义要求。以熟悉的函数形式提供了元素插入、删除 和检索的功能,封装了二叉树的复杂操作。
set 集合容器的C++标准头文件为 set ,需要先用宏语句 "#include <set>" 包含进来方可使用
创建 set 对象
为了管理 set 的二叉树的链表数据,先要利用 set 容器的构造函数,创建一个 set 对象。
1. set()
用默认的 less<T> 函数对象和内存分配器,创建一个没有任何数据元素的 set 对象,例如,下面一行代码创建了一个空的 set 对象 s ,元素类型为 int
set<int> s;
2. set(const key_compare& comp)
指定一个比较函数对象comp 来创建 set 对象,内存分配器为默认值。
例如,下面的的代码使用自定义的函数对象 strLess ,创建一个 set 容器对象 s 。
// 定义字符串比较函数对象 strLess
struct strLess
{
bool operator()(const char* s1, const char* s2) const
{
return strcmp(s1, s2) < 0;
}
};
// 创建 set 容器对象 s
set<const char*, strLess> s(strLess());
// 将1和2对比起来看。 1.是说,创建的set容器对象,默认是从小到大排序的。。。2.是说,可以自己写一个结构体,在创建的时候传入这个结构体,让set 容器元素的排序,按照我们定义的方式来进行。。 。
3. set(const set&)
set拷贝构造函数,通过红黑树的拷贝构造函数,实现两个set容器的元素、头节点和节点个数的拷贝。
下面的代码,利用 set 容器对象 s1 ,拷贝生成 set 容器对象 s2。
// set<int> s1;
set<int> s2(s1);
4. set(InputIterator first, InputIterator last)
用迭代器区间 [first, last) 所指的元素,创建一个 set 对象。
例如,下面代码将数组 iArray 的元素插入到 set 容器对象 s 的红黑树中。
int iArray[] = {13, 32, 19};
set<int> s(iArray, iArray + 3);
5. set(InputIterator first, InputIterator last, const key_compare& comp)
用迭代器区间 [first, last) 所指的元素和 comp 函数对象,创建一个 set 对象。
例如,下面的代码利用上面定义的 strLess 函数对象和数组 szArray ,创建 set 对象 s 。
const char* szArray = {"Hello", "dog", "bird"};
set<const char*, strLess > s(szArray, szArray + 3, strLess());
元素的插入
set 并没有固定的所谓尾部插入 push_back 函数,元素的插入一般使用 insert 进行动态检索插入。
如下的 3 个 insert 函数,或将一个元素插入 set 容器,或将一个迭代器区间的元素加以插入。
1. pair<iterator, bool> insert(const value_type& v)
将元素 v 插入 set 容器,要求 v 值不与 set 容器的任何元素重复,否则插入失败。返回一个 pair 配对对象,提供所插入元素的迭代器位置和 true/false 插入成功标志
2. iterator insert(iteraotr position, const value_type& v)
将元素 v 插入 set 容器,参数 position 只是提示可在 position 位置之前插入 v ,所返回的插入位置视实际情况而定,不一定能在 position 位置前插入。
3. void insert(InputIterator first, InputIterator last)
将某迭代器区间 [first, last) 所指的数据作为元素,插入到 set 容器。
如果希望提供一个是否插入成功的信息,可以使用返回 pair 对象的 insert 函数进行插入,如下面的代码所示。
set<int> sInt;
sInt.insert(10);
pair<set<int>::iterator, bool> p = sInt.insert(19);
if(p.second)
cout<<"插入新元素"<<*(p.first) << endl;
else
cout<<"已存在该元素,不重复插入"<<endl;
元素的删除
与插入一样,set 容器也具有高效的红黑树元素的删除处理,并自动重新调整内部的红黑树平衡。
如下的删除函数,可删除某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和容器的所有元素。
1. void erase(iterator position)
删除 position 所指的元素
2. size_type erase(const key_type& k)
删除等于键值 k 的那个元素,对于 set 容器来说,此函数总是返回值1,因为 set 容器不会出现重复的元素值(键值)
3. void erase(iterator first, iterator last)
删除 set 迭代器区间 [first, last) 上的所有元素
4. void clear()
删除所有元素,但不会删除内部红黑树的头节点
遍历set容器元素:
浅谈一下 pair
------------------------ set 小结
set 集合容器是一个有序关联容器,所包含的元素必须是唯一的,不能插入重复的元素(如果重复插入了,程序会自动舍弃重复的元素)。由于使用了红黑树这种特殊的平衡二叉检索树管理元素数据,具有高效的元素插入、删除和检索。元素检索的算法时间复杂度位 【log2 N】,也即 2 的 N 次方个元素的检索,只需要 N 此比较操作。。。。厉害吧。
pair ,Functor 是比较高级的用法,必须掌握。多看例子,慢慢就能理解了。
set 缺点:不能重复插入相同元素,删除、插入 操作频繁的时候,set 就不适合。
set 优点:对于元素的检索,非常快
原文链接:http://www.cnblogs.com/music-liang/archive/2013/04/05/3000845.html
元素数据的检索,使用的是二叉检索树的中序遍历算法,检索的效率高于 vector 、 deque 和 lsit 等容器。由于采用中序遍历算法可将二叉检索树的键值,由小到大排列遍历出来,因此 set 集合容器蕴含了元素间的有序性。
作为一种关联容器,set 集合容器实现了 Unique Sorted Associative Container 和 Simple Associative Container 概念的函数定义要求。以熟悉的函数形式提供了元素插入、删除 和检索的功能,封装了二叉树的复杂操作。
set 集合容器的C++标准头文件为 set ,需要先用宏语句 "#include <set>" 包含进来方可使用
创建 set 对象
为了管理 set 的二叉树的链表数据,先要利用 set 容器的构造函数,创建一个 set 对象。
1. set()
用默认的 less<T> 函数对象和内存分配器,创建一个没有任何数据元素的 set 对象,例如,下面一行代码创建了一个空的 set 对象 s ,元素类型为 int
set<int> s;
2. set(const key_compare& comp)
指定一个比较函数对象comp 来创建 set 对象,内存分配器为默认值。
例如,下面的的代码使用自定义的函数对象 strLess ,创建一个 set 容器对象 s 。
// 定义字符串比较函数对象 strLess
struct strLess
{
bool operator()(const char* s1, const char* s2) const
{
return strcmp(s1, s2) < 0;
}
};
// 创建 set 容器对象 s
set<const char*, strLess> s(strLess());
// 将1和2对比起来看。 1.是说,创建的set容器对象,默认是从小到大排序的。。。2.是说,可以自己写一个结构体,在创建的时候传入这个结构体,让set 容器元素的排序,按照我们定义的方式来进行。。 。
3. set(const set&)
set拷贝构造函数,通过红黑树的拷贝构造函数,实现两个set容器的元素、头节点和节点个数的拷贝。
下面的代码,利用 set 容器对象 s1 ,拷贝生成 set 容器对象 s2。
// set<int> s1;
set<int> s2(s1);
4. set(InputIterator first, InputIterator last)
用迭代器区间 [first, last) 所指的元素,创建一个 set 对象。
例如,下面代码将数组 iArray 的元素插入到 set 容器对象 s 的红黑树中。
int iArray[] = {13, 32, 19};
set<int> s(iArray, iArray + 3);
5. set(InputIterator first, InputIterator last, const key_compare& comp)
用迭代器区间 [first, last) 所指的元素和 comp 函数对象,创建一个 set 对象。
例如,下面的代码利用上面定义的 strLess 函数对象和数组 szArray ,创建 set 对象 s 。
const char* szArray = {"Hello", "dog", "bird"};
set<const char*, strLess > s(szArray, szArray + 3, strLess());
元素的插入
set 并没有固定的所谓尾部插入 push_back 函数,元素的插入一般使用 insert 进行动态检索插入。
如下的 3 个 insert 函数,或将一个元素插入 set 容器,或将一个迭代器区间的元素加以插入。
1. pair<iterator, bool> insert(const value_type& v)
将元素 v 插入 set 容器,要求 v 值不与 set 容器的任何元素重复,否则插入失败。返回一个 pair 配对对象,提供所插入元素的迭代器位置和 true/false 插入成功标志
2. iterator insert(iteraotr position, const value_type& v)
将元素 v 插入 set 容器,参数 position 只是提示可在 position 位置之前插入 v ,所返回的插入位置视实际情况而定,不一定能在 position 位置前插入。
3. void insert(InputIterator first, InputIterator last)
将某迭代器区间 [first, last) 所指的数据作为元素,插入到 set 容器。
如果希望提供一个是否插入成功的信息,可以使用返回 pair 对象的 insert 函数进行插入,如下面的代码所示。
set<int> sInt;
sInt.insert(10);
pair<set<int>::iterator, bool> p = sInt.insert(19);
if(p.second)
cout<<"插入新元素"<<*(p.first) << endl;
else
cout<<"已存在该元素,不重复插入"<<endl;
元素的删除
与插入一样,set 容器也具有高效的红黑树元素的删除处理,并自动重新调整内部的红黑树平衡。
如下的删除函数,可删除某个迭代器位置上的元素、等于某键值的元素、一个区间上的元素和容器的所有元素。
1. void erase(iterator position)
删除 position 所指的元素
2. size_type erase(const key_type& k)
删除等于键值 k 的那个元素,对于 set 容器来说,此函数总是返回值1,因为 set 容器不会出现重复的元素值(键值)
3. void erase(iterator first, iterator last)
删除 set 迭代器区间 [first, last) 上的所有元素
4. void clear()
删除所有元素,但不会删除内部红黑树的头节点
遍历set容器元素:
/* 解释: 利用【前向】迭代器进行访问,自动将这些整数【由小到大】打印出来 */ ------------------------------------------------------- 遍历 set 容器元素 #include <set> #include <iostream> using namespace std; int main() { // 注意,我插入的元素是乱序、有重复的 set<int> sInt; sInt.insert(10); sInt.insert(15); sInt.insert(11); sInt.insert(17); sInt.insert(13); sInt.insert(19); sInt.insert(19); // 重复插入,被 set 容器舍弃 // 打印二叉树的数据 set<int>::iterator i, iend; 22 iend = sInt.end(); for (i=sInt.begin(); i!=iend; ++i) cout << *i << ' '; cout << endl; return 0; }反向遍历set容器元素
/* 解释: 利用 set 容器定义的【反向迭代器】 reverse_iterator 和 const_reverse_iterator ,可实现红黑树的【逆中序遍历】,从而将元素【由大到小】遍历出来。反向遍历,通常需要用到 rebegin 和 rend 函数,给出反向遍历的开始位置和结束位置。 */ -------------------------------------------------------- 反向遍历 set 容器元素 #include <set> #include <iostream> using namespace std; int main() { // 注意,我插入的元素是乱序、有重复的 set<int> sInt; sInt.insert(10); sInt.insert(15); sInt.insert(11); sInt.insert(17); sInt.insert(12); sInt.insert(18); sInt.insert(18); sInt.insert(18); // 反向 打印二叉树的数据 set<int>::reverse_iterator ri, riend; riend = sInt.rend(); for (ri=sInt.rbegin(); ri!=riend; ++ri) cout << *ri << ' '; cout << endl; return 0; }set容器元素的搜索
/* 解释: set容器提供了一个应用红黑树进行搜索的函数 find ,返回的迭代器值位搜索到的元素位置,如果元素不存在,则返回一个 end 结束元素的位置。 */ -------------------------------------------------------- set 容器元素的搜索 #include <set> #include <iostream> using namespace std; int main() { set<int> sInt; sInt.insert(10); sInt.insert(15); sInt.insert(11); sInt.insert(17); sInt.insert(13); sInt.insert(19); sInt.insert(1); // 搜索元素 13 int v = 13; set<int>::iterator i_v = sInt.find(v); cout << *i_v << endl; // 搜索不存在的元素 100 v = 100; i_v = sInt.find(v); if (i_v != sInt.end()) cout << *i_v << endl; return 0; }set 的 empty 和 size 函数
/* 其他常用函数 empty() size() swap() lower_bound() 下确界函数,返回第一个 > elem 元素的迭代器 upper_bound() 上确界函数,返回第一个 > elem 元素的迭代器 equal_range() 返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。以上函数返回两个迭代器,而这两个迭代器被封装在pair中。以下讲解pair的含义与使用方法。 */ -------------------------------------------------------- set 的 empty 和 size 函数 #include <set> #include <iostream> using namespace std; int main() { set<int> sInt; sInt.insert(5); sInt.insert(6); sInt.insert(7); sInt.insert(8); sInt.insert(4); // 打印元素个数 if (sInt.empty()) cout << "set 容器为空" << endl; else cout << "set 容器元素个数为:" << sInt.size() << endl; return 0; }
浅谈一下 pair
------------------------------ 浅谈一下 pair (在关于 map 容器的笔记中,会更多地用到 pair. pair 很强大的,这里只是小试牛刀而已) pair译为对组,可以将两个值视为一个单元。 pair<T1,T2>存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可以是自定义类型。 pair.first是pair里面的第一个值,是T1类型。 pair.second是pair里面的第二个值,是T2类型 // pair 和 equal_range 的配合使用 例如 set<int> setInt; ... //往setInt容器插入元素1,3,5,7,9 pair< set<int>::iterator , set<int>::iterator > pairIt = setInt.equal_range(5); set<int>::iterator itBeg = pairIt.first; set<int>::iterator itEnd = pairIt.second; //此时 *itBeg==5 而 *itEnd == 7浅谈一下 functor
<pre name="code" class="cpp"> ------------------------- 浅谈一下 functor 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。 functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的普通类对象。从语法上讲,它与普通函数行为类似。 // 题目:学生包含学号,姓名属性,现要求任意插入几个学生对象到set容器中,使得容器中的学生按学号的升序排序。 #pragma warning(disable:4786) #include <set> #include <iostream> using namespace std; // 学生类 class CStudent { public: CStudent(int nID, string strName) { m_nID = nID; m_strName = strName; } public: int m_nID; string m_strName; }; // 函数对象 , 多看几遍,找一些相关的例子,就能理解了 struct studentFunctor { bool operator() (const CStudent &stu1, const CStudent &stu2) { return (stu1.m_nID < stu2.m_nID); } }; int main() { set<CStudent, studentFunctor> setStu; setStu.insert(CStudent(3, "小张")); setStu.insert(CStudent(1, "小李")); setStu.insert(CStudent(5, "小王")); setStu.insert(CStudent(7, "小军")); set<CStudent, studentFunctor>::iterator it,itend; itend = setStu.end(); // 按 ID 顺序,从小到大排列 for (it=setStu.begin(); it!=itend; ++it) { // 字符串,用 c_str() 函数来显示(string容器会讨论) cout << it->m_strName.c_str() << " "; } return 0; }
------------------------ set 小结
set 集合容器是一个有序关联容器,所包含的元素必须是唯一的,不能插入重复的元素(如果重复插入了,程序会自动舍弃重复的元素)。由于使用了红黑树这种特殊的平衡二叉检索树管理元素数据,具有高效的元素插入、删除和检索。元素检索的算法时间复杂度位 【log2 N】,也即 2 的 N 次方个元素的检索,只需要 N 此比较操作。。。。厉害吧。
pair ,Functor 是比较高级的用法,必须掌握。多看例子,慢慢就能理解了。
set 缺点:不能重复插入相同元素,删除、插入 操作频繁的时候,set 就不适合。
set 优点:对于元素的检索,非常快
原文链接:http://www.cnblogs.com/music-liang/archive/2013/04/05/3000845.html
相关文章推荐
- HDU 2018 母牛的故事
- apache kafka系列之server.properties配置文件参数说明
- IBM Bluemix 问题-MySQL
- android webview 获取Geolocation
- Y must be a vector or a character array
- CSS(5)-选择器
- Linux安装kafka 分布式
- 接口测试-自动化-Java实现-TestMain
- Variety 1st 尝试前端工程师 (1)
- myeclipse2015-version-comparison.pdf
- Vmware vSphere 5.0实战教程之四 VMware HA实战
- [JSP 笔记]01_JSP 简介
- ios开发-成员变量,属性变量随笔
- 如何判断一个请求为ajax请求?
- Delphi+GDI
- 14个Xcode中常用的快捷键操作
- 史上最简单Robotium跨进程操作实践——基于ADB框架
- java学习路线
- Maven打包过程中跳过测试
- Java实现获取文件MD5