关于set,必须说明的是set关联式容器。set作为一个容器也是用来存储同一数据类型的数据类型,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中数元素的值不能直接被改变。C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树,所以被STL选择作为了关联容器的内部结构。
为何每次insert之后,以前保存的iterator不会失效?
iterator这里就相当于指向节点的指针,内存没有变,指向内存的指针怎么会失效呢(当然被删除的那个元素本身已经失效了)。相对于vector来说,每一次删除和插入,指针都有可能失效,调用push_back在尾部插入也是如此。因为为了保证内部数据的连续存放,iterator指向的那块内存在删除和插入过程中可能已经被其他内存覆盖或者内存已经被释放了。即使时push_back的时候,容器内部空间可能不够,需要一块新的更大的内存,只有把以前的内存释放,申请新的更大的内存,复制已有的数据元素到新的内存,最后把需要插入的元素放到最后,那么以前的内存指针自然就不可用了。特别时在和find等算法在一起使用的时候,牢记这个原则:不要使用过期的iterator。
set 与 multiset底层都采用红黑树实现,其key-value相容,multiset允许元素重复,set与map一样,自动排序,默认升序
erase(iterator) ,删除定位器iterator指向的值
erase(first,second),删除定位器first和second之间的值
erase(key_value),删除键值key_value的值
#include <iostream> #include <set> using namespace std; int main() { set<int> s; set<int>::const_iterator iter; set<int>::iterator first; set<int>::iterator second; for(int i = 1 ; i <= 10 ; ++i) { s.insert(i); } //第一种删除 s.erase(s.begin()); //第二种删除 first = s.begin(); second = s.begin(); second++; second++; s.erase(first,second); //第三种删除 s.erase(8); cout<<"删除后 set 中元素是 :"; for(iter = s.begin() ; iter != s.end() ; ++iter) { cout<<*iter<<" "; } cout<<endl; return 0; }
#include <iostream> #include <set> using namespace std; int main() { int a[] = {1,2,3}; set<int> s(a,a+3); set<int>::iterator iter; if((iter = s.find(2)) != s.end()) { cout<<*iter<<endl; } return 0; }
insert(key_value); 将key_value插入到set中 ,返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
inset(first,second); 将定位器first到second之间的元素插入到set中,返回值是void
#include <iostream> #include <set> using namespace std; int main() { int a[] = {1,2,3}; set<int> s; set<int>::iterator iter; s.insert(a,a+3); for(iter = s.begin() ; iter != s.end() ; ++iter) { cout<<*iter<<" "; } cout<<endl; pair<set<int>::iterator,bool> pr; pr = s.insert(5); if(pr.second) { cout<<*pr.first<<endl; } return 0; }