c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器。
set/multiset会根据待定的排序准则,自动将元素排序。两者不同在于前者不允许元素重复,而后者允许。
c++ stl集合set介绍
c++ stl集合(Set)是一种包含已排序对象的关联容器。set/multiset会根据待定的排序准则,自动将元素排序。两者不同在于前者不允许元素重复,而后者允许。
1) 不能直接改变元素值,因为那样会打乱原本正确的顺序,要改变元素值必须先删除旧元素,则插入新元素
2) 不提供直接存取元素的任何操作函数,只能通过迭代器进行间接存取,而且从迭代器角度来看,元素值是常数
3) 元素比较动作只能用于型别相同的容器(即元素和排序准则必须相同)
set模板原型://Key为元素(键值)类型
1 |
|
从原型可以看出,可以看出比较函数对象及内存分配器采用的是默认参数,因此如果未指定,它们将采用系统默认方式。
set的各成员函数列表如下:
c++ stl容器set成员函数:begin()--返回指向第一个元素的迭代器
c++ stl容器set成员函数:clear()--清除所有元素
c++ stl容器set成员函数:count()--返回某个值元素的个数
c++ stl容器set成员函数:empty()--如果集合为空,返回true
c++ stl容器set成员函数:end()--返回指向最后一个元素的迭代器
c++ stl容器set成员函数:equal_range()--返回集合中与给定值相等的上下限的两个迭代器
c++ stl容器set成员函数:erase()--删除集合中的元素
c++ stl容器set成员函数:find()--返回一个指向被查找到元素的迭代器
c++ stl容器set成员函数:get_allocator()--返回集合的分配器
c++ stl容器set成员函数:insert()--在集合中插入元素
c++ stl容器set成员函数:lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
c++ stl容器set成员函数:key_comp()--返回一个用于元素间值比较的函数
c++ stl容器set成员函数:max_size()--返回集合能容纳的元素的最大限值
c++ stl容器set成员函数:rbegin()--返回指向集合中最后一个元素的反向迭代器
c++ stl容器set成员函数:rend()--返回指向集合中第一个元素的反向迭代器
c++ stl容器set成员函数:size()--集合中元素的数目
c++ stl容器set成员函数:swap()--交换两个集合变量
c++ stl容器set成员函数:upper_bound()--返回大于某个值元素的迭代器
c++ stl容器set成员函数:value_comp()--返回一个用于比较元素间的值的函数
常用操作:
1.元素插入:insert()
2.中序遍历:类似vector遍历(用迭代器)
3.反向遍历:利用反向迭代器reverse_iterator。
例:
1 set<int> s; 2 ...... 3 set<int>::reverse_iterator rit; 4 for(rit=s.rbegin();rit!=s.rend();rit++)
4.元素删除:与插入一样,可以高效的删除,并自动调整使红黑树平衡。
1 set<int> s; 2 s.erase(2); //删除键值为2的元素 3 s.clear();
5.元素检索:find(),若找到,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置。
1 set<int> s; 2 set<int>::iterator it; 3 it = s.find(5); //查找键值为5的元素 4 if (it != s.end()) //找到 5 cout << *it << endl; 6 else //未找到 7 cout << "未找到";
6.自定义比较函数
(1)元素不是结构体:
例:
//自定义比较函数myComp,重载“()”操作符
1 struct myComp 2 { 3 bool operator()(const your_type &a, const your_type &b){ 4 return a.data - b.data > 0; 5 } 6 } 7 set<int, myComp>s; 8 ...... 9 set<int, myComp>::iterator it; erator it;
(2)如果元素是结构体,可以直接将比较函数写在结构体内。
例:
1 struct Info 2 { 3 string name; 4 float score; 5 //重载“<”操作符,自定义排序规则 6 bool operator < (const Info &a) const 7 { 8 //按score从大到小排列 9 return a.score<score; 10 } 11 } 12 set<Info> s; 13 ...... 14 set<Info>::iterator it;
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 //set插入元素操作 5 int main() 6 { 7 //定义一个int型集合对象s,当前没有任何元素.由www.169it.com搜集整理 8 set<int> s; 9 s.insert(8); //第一次插入8,可以插入 10 s.insert(1); 11 s.insert(12); 12 s.insert(6); 13 s.insert(8); //第二次插入8,重复元素,不会插入 14 set<int>::iterator it; //定义前向迭代器 15 for(it=s.begin();it!=s.end();it++) 16 cout<<*it<<endl; 17 system("pause"); 18 return 0; 19 }
其他用法如下
1 #include <iostream> 2 #include <iterator> 3 #include <set> 4 #include <algorithm> 5 using namespace std; 6 int main() 7 { 8 set<int> eg1; 9 eg1.insert(1); 10 eg1.insert(100); 11 eg1.insert(5); 12 eg1.insert(1); //元素1因为已经存在所以set中不会再次插入1 13 eg1.insert(10); 14 eg1.insert(9); 15 //遍历set,可以发现元素是有序的 16 set<int>::iterator set_iter = eg1.begin(); 17 cout << "Set named eg1:" << endl; 18 for (; set_iter != eg1.end(); set_iter++) cout << *set_iter << " "; 19 cout << endl; 20 //使用size()函数可以获得当前元素个数 21 cout << "Now there are " << eg1.size() << " elements in the set eg1" << endl; 22 if (eg1.find(200) == eg1.end())//find()函数可以查找元素是否存在 23 cout << "200 isn't in the set eg1" << endl; 24 25 26 27 set<int> eg2; 28 for (int i = 6; i < 15; i++) 29 eg2.insert(i); 30 cout << "Set named eg2:" << endl; 31 for (set_iter = eg2.begin(); set_iter != eg2.end(); set_iter++) 32 cout << *set_iter << " "; 33 cout << endl; 34 35 //获得两个set的并 36 set<int> eg3; 37 cout << "Union(两个set的并集):"; 38 set_union(eg1.begin(), 39 eg1.end(), 40 eg2.begin(), 41 eg2.end(), 42 insert_iterator<set<int> >(eg3, eg3.begin()) 43 );//注意第五个参数的形式 44 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 45 cout << endl; 46 47 //获得两个set的交,注意进行集合操作之前接收结果的set要调用clear()函数清空一下 48 eg3.clear(); 49 set_intersection(eg1.begin(), 50 eg1.end(), 51 eg2.begin(), 52 eg2.end(), 53 insert_iterator<set<int> >(eg3, eg3.begin()) 54 ); 55 cout << "Intersection:"; 56 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 57 cout << endl; 58 59 //获得两个set的差 60 eg3.clear(); 61 set_difference(eg1.begin(), 62 eg1.end(), eg2.begin(), 63 eg2.end(), 64 insert_iterator<set<int> >(eg3, eg3.begin()) 65 ); 66 cout << "Difference:"; 67 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 68 cout << endl; 69 70 //获得两个set的对称差,也就是假设两个集合分别为A和B那么对称差为AUB-A∩B 71 eg3.clear(); 72 set_symmetric_difference(eg1.begin(), eg1.end(), eg2.begin(), eg2.end(), insert_iterator<set<int> >(eg3, eg3.begin())); 73 copy(eg3.begin(), eg3.end(), ostream_iterator<int>(cout, " ")); 74 cout << endl; 75 76 return 0; 77 } 78 79 80 81 下面给出一个关键字类型为char*的示例代码 82 83 #include<iostream> 84 #include<iterator> 85 #include<set> 86 using namespace std; 87 struct ltstr 88 { 89 bool operator() (const char* s1, const char* s2) const 90 { 91 return strcmp(s1, s2) < 0; 92 } 93 }; 94 95 int main() 96 { 97 const int N = 6; 98 const char* a[N] = { "isomer", "ephemeral", "prosaic", 99 "nugatory", "artichoke", "serif" }; 100 const char* b[N] = { "flat", "this", "artichoke", 101 "frigate", "prosaic", "isomer" }; 102 103 set<const char*, ltstr> A(a, a + N); 104 set<const char*, ltstr> B(b, b + N); 105 set<const char*, ltstr> C; 106 107 cout << "Set A: "; 108 //copy(A.begin(), A.end(), ostream_iterator<const char*>(cout, " ")); 109 set<const char*, ltstr>::iterator itr; 110 for (itr = A.begin(); itr != A.end(); itr++) cout << *itr << " "; 111 cout << endl; 112 cout << "Set B: "; 113 copy(B.begin(), B.end(), ostream_iterator<const char*>(cout, " ")); 114 cout << endl; 115 116 cout << "Union: "; 117 set_union(A.begin(), A.end(), B.begin(), B.end(), 118 ostream_iterator<const char*>(cout, " "), 119 ltstr()); 120 cout << endl; 121 122 cout << "Intersection: "; 123 set_intersection(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator<const char*>(cout, " "), ltstr()); 124 cout << endl; 125 set_difference(A.begin(), A.end(), B.begin(), B.end(), inserter(C, C.begin()), ltstr()); 126 cout << "Set C (difference of A and B): "; 127 copy(C.begin(), C.end(), ostream_iterator<const char*>(cout, " ")); 128 cout << endl; 129 return 0; 130 } 131 132 其中的ltstr也可以这样定义 133 class ltstr 134 { 135 public: 136 bool operator() (const char* s1, const char*s2)const 137 { 138 return strcmp(s1, s2) < 0; 139 } 140 }; 141 142 更加通用的应用方式那就是数据类型也是由用户自定义的类来替代,比较的函数自定义,甚至可以加上二级比较,比如首先按照总分数排序,对于分数相同的按照id排序,下面是示例代码 143 144 #include<set> 145 #include<iostream> 146 using namespace std; 147 struct 148 { 149 int id; 150 int score; 151 string name; 152 }; 153 struct compare 154 { 155 bool operator()(const Entity& e1, const Entity& e2)const { 156 if (e1.score < e2.score) return true; 157 else 158 if (e1.score == e2.score) 159 if (e1.id < e2.id) return true; 160 161 return false; 162 } 163 }; 164 165 int main() 166 { 167 set<Entity, compare>s_test; 168 Entity a, b, c; 169 a.id = 123; a.score = 90; a.name = "bill"; 170 b.id = 121; b.score = 85; b.name = "mary"; 171 c.id = 130; c.score = 85; c.name = "jerry"; 172 s_test.insert(a); s_test.insert(b); s_test.insert(c); 173 set<Entity, compare>::iterator itr; 174 cout << "Score List(ordered by score):\n"; 175 for (itr = s_test.begin(); itr != s_test.end(); itr++) 176 cout << itr->id << "---" << itr->name << "---" << itr->score << endl; 177 return 0; 178 }