C++(20):STL初步之set初步

来源:互联网 发布:php 权限管理 员工权限 编辑:程序博客网 时间:2024/05/16 17:31

set,集合。关联容器。

可以自己指定存储顺序。

默认以"<"进行排序。

存obj,但这些obj都作为set的key值,不可重复出现。

set只有key,无value。迭代器是const的。因为不能改变key!

#include <iostream>#include <set>using namespace std;void showSet(set<char> & set1) {for (auto key:set1){cout<<key<<" ";}cout<<"\n";}int main() {set<char> set1;set1.insert('d');set1.insert('c');set1.insert('b');set1.insert('a');showSet(set1);set1.insert('c'); // 不能重复!set是集合!showSet(set1);//auto number =  set.erase('key值'); // 对于关联容器,用key值删除里面的元素,返回的是删掉元素的个数!auto res1 = set1.erase('a'); // 删除元素!输入参数可以是set里的key值。返回的是size_type类型。cout<<res1<<endl; // 删除成功,返回1showSet(set1);auto res2 = set1.erase('f'); // 删除不存在的元素,返回0cout<<res2<<endl;showSet(set1);// 用迭代器去删除set里的元素// 【严重警告】 千万不要这样写!!!// 报错!// 在删掉元素以后,说不定内存就已经被回收了!因为没有更新it,it在++的时候,// 说不定it就非法访问了!!!set<char> :: iterator  it;for (it = set1.begin();it!=set1.end();it++){if (*it == 'c'){// 【严重警告】// set1.erase(it); // 不把删掉后的返回值,赋给it,循环会出问题!// 必须把删掉元素后的返回值,赋给it!!// 否则就break or return;// 以下写法OKit = set1.erase(it); if (it!=set1.end()) { cout<<"删除成功"<<endl; }}}system("pause");return 0;}

a b c d
a b c d
1
b c d
0
b c d
删除成功


注意删除的两种写法。

通过迭代器遍历去删除,一定、一定、一定!要把erase的返回值,赋值给迭代器!!


关于set中元素的查询。

// 查询auto it = set1.find('d');if (it!=set1.end()){cout<<"找到"<<endl;// it = 'd'; // 错误! // key是const!}

据说:STL里的set是基于红黑树实现的。

set<int> dataSet;for (int i = 10;i!=0;i--){dataSet.insert(i);}set<int> :: iterator it1;for (it1 = dataSet.begin();it1!=dataSet.end();it1++){cout<<*it1<<" ";}cout<<"\n";
会输出1 2 3 ... 10

默认从小到大排序

如果希望从大到小排序,需要指定排序方式。

自定义排列顺序

又用到仿函数。

#include <iostream>#include <set>using namespace std;class large2small{public:bool operator() (int x,int y) {return (x>y);}};int main() {set<int> dataSet;for (int i = 10;i!=0;i--){dataSet.insert(i);}set<int> :: iterator it1;for (it1 = dataSet.begin();it1!=dataSet.end();it1++){cout<<*it1<<" ";}cout<<"\n";set<int,large2small> dataSet2;for (int i = 1;i<=10;i++){dataSet2.insert(i);}for (auto i : dataSet2){cout<<i<<" ";}cout<<"\n";system("pause");return 0;}
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1

其中,dataSet,没有指定排列顺序,dataSet2,指定了从大到小排列!


以下内容来自网络

====================================

Q:STL中set底层实现方式? 为什么不用hash?

A: 第一个问题:set底层实现方式为RB树(即红黑树)。
第二个问题:
首先set,不像map那样是key-value对,它的key与value是相同的。关于set有两种说法,第一个是STL中的set,用的是红黑树;第二个是hash_set,底层用得是hash table。红黑树与hash table最大的不同是,红黑树是有序结构,而hash table不是。但不是说set就不能用hash,如果只是判断set中的元素是否存在,那么hash显然更合适,因为set 的访问操作时间复杂度是log(N)的,而使用hash底层实现的hash_set是近似O(1)的。然而,set应该更加被强调理解为“集合”,而集合所涉及的操作并、交、差等,即STL提供的如交集set_intersection()、并集set_union()、差集set_difference()和对称差集set_symmetric_difference(),都需要进行大量的比较工作,那么使用底层是有序结构的红黑树就十分恰当了,这也是其相对hash结构的优势所在。

0 0