关于C++STL中set集合容器的学习,看别人的代码一百遍,不如自己动手写一遍。
构造set集合容器的目的是为了去重+排序+快速搜索。由于set集合容器实现了红黑树多的平衡二叉检索树的数据结构,在插入或者删除是,均能自动调整二叉树,使得二叉树始终保持新的平衡。除set外,multiset,map,multimap的内部结构也是平衡二叉树。
1 /*关于C++STL中set集合容器的学习,看别人的代码一百遍,不如自己动手写一遍。 2 set集合容器的主要目的是为了加快检索,当有某种数据类型需要去重加排序的时候,使用起来去重非常方便, 3 而且查找效率非常高。 4 */ 5 #include <set>//头文件,与multiset相同 6 #include <iostream> 7 using namespace std; 8 9 //自定义比较函数myComp,重载"()"操作符 10 struct myComp{ 11 bool operator () (const int &a,const int &b){ 12 return a>b;//由大到小 13 } 14 }; 15 16 //直接将比较函数写在结构体内 17 struct STUDENT{ 18 string name; 19 double score; 20 21 //重载"<"操作符,自定义排列规则 22 bool operator < (const STUDENT &a) const{ 23 //按score由大到小排列。如果由小到大排列,使用">"号即可 24 return a.score < score; 25 } 26 }; 27 28 void print(set<int> s); 29 void rprint(set<int> s); 30 31 int main() 32 { 33 /*创建set集合对象,格式为set<元素类型> 集合对象标识符*/ 34 set<int> s;//定义了一个元素类型为int的集合对象s,当前没有任何元素 35 36 /*元素的插入和遍历(对平衡二叉检索树的中序遍历)*/ 37 //插入过程也是排序过程,排序采用默认的比较规则,使得set集合的数据结构始终保持平衡二叉检索树 38 //也可以自定义比较规则函数 39 s.insert(8);//第一次插入8,可以插入 40 s.insert(1); 41 s.insert(6); 42 s.insert(12); 43 s.insert(8);//第二次插入8,重复元素,不可以插入,从而达到去重的效果 44 45 //中序正向遍历集合中的所有元素 46 set<int>::iterator it;//定义前向迭代器 47 for(it=s.begin(); it != s.end(); it++){ 48 cout<<*it<<' '; 49 } 50 cout<<endl; 51 /*运行结果 52 1 6 8 12 53 */ 54 //中序反向遍历集合中的所有元素 55 set<int>::reverse_iterator rit; 56 for(rit=s.rbegin(); rit != s.rend();rit++){ 57 cout<<*rit<<' '; 58 } 59 cout<<endl; 60 /*运行结果 61 12 8 6 1 62 */ 63 64 /*要想检索集合中是否存在等于某个键值的元素,则使用find()方法,如果找到则返回该键值的迭代器位置, 65 否则,返回集合最后一个元素后面的一个位置,即end()*/ 66 set<int>::iterator it1;//定义迭代器接收find()方法的返回值 67 it1=s.find(12); 68 if(it1 != s.end()) 69 cout<<"找到键值为 "<<*it1<<"的元素\n"; 70 it1=s.find(2); 71 if(it1 == s.end()) 72 cout<<"没有找到键值为 1的元素\n"; 73 /*运行结果 74 找到键值为 12的元素 75 没有找到键值为 1的元素 76 */ 77 78 /*元素的删除*/ 79 //要想删除等于某个键值时,使用erase()方法 80 cout<<"删除前:\n"; 81 print(s); 82 s.erase(6);//删除键值为6这个元素 83 cout<<"删除后:\n"; 84 print(s); 85 /*运行结果 86 删除前: 87 1 6 8 12 88 删除后: 89 1 8 12 90 */ 91 92 //要想清空集合 93 cout<<"清空前:\n"; 94 print(s); 95 s.clear(); 96 cout<<"清空后:\n"; 97 print(s); 98 /*运行结果 99 清空前: 100 1 8 12 101 清空后: 102 103 */ 104 105 /*注意使用insert()将元素插入到集合中去的时候,集合会根据设定的比较函数将元素放到相应的结点上。当没有制定比较 106 函数的时候采用默认比较函数,即按键值由小到大的顺序插入*/ 107 108 /*插入时编写比较函数的两种方法*/ 109 //如果元素是基本数据类型,见main函数之前的定义方法 110 set<int,myComp> ss; 111 ss.insert(8);//同样,第一次插入,第二次重复元素不插入 112 ss.insert(1); 113 ss.insert(12); 114 ss.insert(6); 115 116 set<int,myComp>::iterator it2;//定义同元素类型的前向迭代器 117 for(it2=ss.begin(); it2 != ss.end(); it2++){ 118 cout<<*it2<<' '; 119 } 120 cout<<endl; 121 /*运行结果 122 12 8 6 1 123 */ 124 125 //如果元素是结构体,可以将比较函数写在结构体内,见main函数之前的定义方法 126 set<STUDENT> students; 127 STUDENT someone; 128 someone.name="Jack"; 129 someone.score=80.5; 130 students.insert(someone); 131 132 someone.name="Tomi"; 133 someone.score=57.5; 134 students.insert(someone); 135 136 someone.name="Nacy"; 137 someone.score=60.5; 138 students.insert(someone); 139 140 set<STUDENT>::iterator it3;//定义前向迭代器 141 for(it3=students.begin(); it3 != students.end();it3 ++){ 142 cout<<(*it3).name<<":"<<(*it3).score<<endl; 143 } 144 /*运行结果 145 Jack:80.5 146 Nacy:60.5 147 Tomi:57.5 148 */ 149 return 0; 150 } 151 152 void print(set<int> s) 153 { 154 set<int>::iterator it;//定义前向迭代器 155 for(it=s.begin(); it != s.end(); it++){ 156 cout<<*it<<' '; 157 } 158 cout<<endl; 159 } 160 161 void rprint(set<int> s) 162 { 163 set<int>::reverse_iterator rit;//定义反向迭代器 164 for(rit=s.rbegin(); rit != s.rend();rit++){ 165 cout<<*rit<<' '; 166 } 167 cout<<endl; 168 }