一、set概述
set是一個關聯式容器,set中,元素都是唯一的,並且在往set中添加元素的時候,會根據元素的值進行自動排序。其內部採用的數據結構是紅黑樹,紅黑樹是一種非常高效的平衡檢索二叉樹。讀者若有興趣,可自行查閱相關資料。set的插入和搜索速度是很快的,set中使用的是二分查找,是log的關係。比如有16個元素的set,最多需要查找4次,有10000個元素,最多需要查找14次,就算元素再增加一倍,達到20000個,最多需要查找15次,也只是多了一次查找而已。
1、爲什麼set插入、刪除的效率比較高?
對於set來講,不需要內存拷貝和內存移動,set中元素是以節點的方式存儲的,插入數據的時候只需要做相應的節點變換即可,刪除操作也是類似的,與內存拷貝、內存移動沒有任何關係。
2、每次insert後,之前保存的iterator是否會失效?
插入元素的時候,並沒有涉及到內存拷貝和內存移動,內存沒有變,故不會失效。
二、set的使用
set內部元素是有序的,如果存放的是內置數據類型,會按照默認排序。如果存放自定義數據類型則需要自定義排序。當然,內置數據類型也可以使用自定義排序。
1、自定義排序
方式一:重載<
class Student{
public:
std::string name_;
int age_;
Student(std::string name, int age):name_(name),age_(age){}
Student(){}
bool operator < (const Student &s) const {
if(name_ != s.name_){
return name_ < s.name_;
}else{
return age_ < s.age_;
}
}
std::string show(){
return "name:" + name_ + ", age:" + std::to_string(age_);
}
};
int main(int argc, char *argv[]) {
set<Student> s;
s.emplace(Student("Danney", 22));
s.emplace(Student("LiMing", 20));
s.emplace(Student("LiMing", 18));
for(auto it : s){
cout << it.show() << endl;
}
return 0;
}
方式二:重載()
class Student{
public:
std::string name_;
int age_;
Student(std::string name, int age):name_(name),age_(age){}
Student(){}
std::string show(){
return "name:" + name_ + ", age:" + std::to_string(age_);
}
};
class Comp{
public:
bool operator () (const Student &left, const Student &right){
if(left.name_ != right.name_){
return left.name_ < right.name_;
}else{
return left.age_ < right.age_;
}
}
};
int main(int argc, char *argv[]) {
set<Student, Comp> s;
s.emplace(Student("Danney", 22));
s.emplace(Student("LiMing", 20));
s.emplace(Student("LiMing", 18));
for(auto it : s){
cout << it.show() << endl;
}
return 0;
}
方式三:
class Student{
public:
std::string name_;
int age_;
Student(std::string name, int age):name_(name),age_(age){}
Student(){}
std::string show(){
return "name:" + name_ + ", age:" + std::to_string(age_);
}
};
bool comp (const Student &left, const Student &right){
if(left.name_ != right.name_){
return left.name_ < right.name_;
}else{
return left.age_ < right.age_;
}
}
int main(int argc, char *argv[]) {
set<Student, decltype(comp)*> s(comp);
s.emplace(Student("Janney", 23));
s.emplace(Student("Danney", 22));
s.emplace(Student("LiMing", 20));
s.emplace(Student("LiMing", 18));
for(auto it : s){
cout << it.show() << endl;
}
return 0;
}
2、添加元素:三種方式
set<int> sInt;
//元素添加
//1、返回pair對象,second表示是否添加成功
pair<set<int>::iterator, bool > isSu = sInt.insert(5);
if(isSu.second){
cout << "successful!" << endl;
}
//2、在iterator前插入元素 insert(&pos, value),返回新元素的位置
sInt.insert(isSu.first,9);
//3、添加區間,將區間[&first, &last)區間內的元素添加到set中
int array[] = {4, 10, 6};
sInt.insert(array, array+3);
3、刪除元素:四種方式
//元素刪除
//1、erase(value),返回移除元素的個數
auto num = sInt.erase(6);
cout << "移除元素個數:" << num << endl;
//2、erase(&pos),移除pos上的元素,無返回值
auto iter = sInt.begin();
sInt.erase(iter);
for(auto it : sInt){
cout << it << ", ";
}
//3、erase(&first, &last),移除[&first, &last)區間內的元素
sInt.erase(sInt.begin(), sInt.end());
cout << endl << "after [fir, last) : " << endl;
for(auto it : sInt){
cout << it << ", ";
}
//4、移除所有元素
sInt.clear();
cout << endl << "after clear : " << endl;
for(auto it : sInt){
cout << it << ", ";
}
4、查找
//查找
//1、count(value),返回value的個數
cout << sInt.count(10) << endl;
//2、iterator find(value),返回value的位置,如果找不到,則返回end()
auto res_find_f = sInt.find(10);
if(res_find_f == sInt.end()){
cout << "未找到" << endl;
}else{
cout << "已找到" << endl;
}
auto res_find_s = sInt.find(20);
if(res_find_s == sInt.end()){
cout << "未找到" << endl;
}else{
cout << "已找到" << endl;
}
5、其他
begin():返回set的第一個元素
end():返回set最後一個元素的下一個位置
empty():判斷是否爲空
max_size():返回set中可能包含的元素個數最大值
size():返回當前元素個數
rbegin():與end()返回值相同
rend():與begin()返回值相同