C++ -- STL泛型编程(二)之set
set集合容器实现了红黑树的平衡二叉检索树的数据结构,在插入元素时候它会自动调整二叉树的排列,把元素放在适当的位置,以确保每个子树根节点的键值都大于左子树的所有节点的键值,而小于右子树的所有节点的键值;另外,还得确保根节点的左子树的高度与右子树的高度相等,这样,二叉树的高度最小,从而是检索的速度最快。要注意的是,它不会重复插入相同的键值,而采取忽略处理。
平衡二叉树的检索方法使用中序遍历算法,检索效率高于vector,deque和list等容器。
对于set容器中的键值,不可以直接去修改。因为如果把容器中的一个键值改了,set容器会根据新的键值旋转子树,以保持新的平衡,这样修改的键值可能就不在原先的位置了。换句话说,构造set集合的主要目的就是为了快速检索。multiset(多重集合容器),map(映照容器)和multimap(多重映照容器)的内部结构都是平衡二叉检索树。
1 //元素的插入与中序遍历 2 #include<iostream> 3 #include<set> 4 using namespace std; 5 6 int main(int argc,char *argv[]) 7 { 8 set<int>s; 9 s.insert(8); 10 s.insert(6); 11 s.insert(10); 12 s.insert(1); 13 s.insert(8);//第二次插入8,重复元素,不会插入 14 15 set<int>::iterator it;//定义前向迭代器 16 17 for(it=s.begin();it!=s.end();it++)//中序遍历容器中的所有元素 18 cout<<*it<<" "; 19 cout<<endl; //运行结果:1 6 8 10 20 21 set<int>::reverse_iterator rit;//反向遍历 22 for(rit=s.rbegin();rit!=s.rend();rit++) 23 cout<<*rit<<" "; 24 cout<<endl; //运行结果:10 8 6 1 25 return 0; 26 }
set容器之元素的检索,使用find()方法对集合进行搜索,如果找的查找的键值,则返回
该键值的迭代器位置,否则返回集合最后一个元素后面的一个位置,即end()。
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 5 int main(int argc,int argv[]) 6 { 7 set<int>s; 8 9 s.insert(8); 10 s.insert(1); 11 s.insert(12); 12 s.insert(6); 13 14 s.insert(8); 15 set<int>::iterator it; 16 it=s.find(6); 17 18 if(it!=s.end()) 19 cout<<*it<<endl; 20 else 21 cout<<"not find it"<<endl; 22 23 it=s.find(20); 24 25 if(it!=s.end()) 26 cout<<*it<<endl; 27 else 28 cout<<"not find it"<<endl; 29 return 0; 30 } 31 32 /* 33 运行结果: 34 6 35 not find it 36 */
set容器编写比较函数有两种方法:
(1)如果元素不是结构体,那么,可以编写比较函数。
(2)如果元素是结构体,那么,可以直接把比较函数写在结构体内。
第一方法:如果元素不是结构体,那么,可以编写比较函数。
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 5 struct myComp 6 { 7 bool operator()(const int &a,const int &b) 8 { 9 if(a!=b) 10 return a>b; 11 else 12 return a>b; 13 } 14 }; 15 16 int main(int argc,char *argv[]) 17 { 18 set<int,myComp>s; 19 s.insert(8); 20 s.insert(1); 21 s.insert(12); 22 s.insert(6); 23 s.insert(8); 24 set<int,myComp>::iterator it; 25 26 for(it=s.begin();it!=s.end();it++) 27 cout<<*it<<" "; 28 cout<<endl; 29 return 0; 30 } 31 32 //运行结果:12 8 6 1
第二种方法:如果元素是结构体,那么,可以直接把比较函数写在结构体内。
1 #include<iostream> 2 #include<set> 3 #include<string> 4 using namespace std; 5 6 struct Info 7 { 8 string name; 9 double score; 10 bool operator<(const Info &a)const 11 { 12 return a.score<score; 13 } 14 }; 15 16 int main(int argc,char *argv[]) 17 { 18 set<Info>s; 19 Info info; 20 21 info.name="Tom"; 22 info.score=80.5; 23 s.insert(info); 24 25 info.name="Nacy"; 26 info.score=60.8; 27 s.insert(info); 28 29 info.name="Jack"; 30 info.score=90.8; 31 s.insert(info); 32 33 set<Info>::iterator it; 34 for(it=s.begin();it!=s.end();it++) 35 cout<<(*it).name<<" "<<(*it).score<<endl; 36 return 0; 37 } 38 /* 39 运行结果: 40 Jack 90.8 41 Tom 80.5 42 Nacy 60.8 43 */