前言:今天我们来分享STL标准库容器set
关联式容器和序列式容器
序列式容器:我们学过的vector list deque forward_list都是序列式容器,底层都是线性的数据结果,存储的都是元素本身
关联式容器:存储的是的结构,在数据的搜索方便比序列式容器效率高
二者的区别:
(1)关联式容器是按关键字进行存储和访问的,而序列式容器是按元素在容器中的位置进行顺序存储和访问的
(2)关联式容器元素是按key值进行排序的(默认是升序),序列式容器按元素插入顺序进行排序
(3)序列式容器支持随机访问,关联式容器不支持随机访问,但是提供高效的查找功能,set是通过key进行快速的查找元素
键值对
表示一种一一对应的一种结构,该结构中一般包含两个成员变量(key,value),key表示键值,value表示与key对应的信息;举个例子,现在有一个英汉互译的软件,那么该软件中的英语单词必然有一个对应的汉语含义,所以通过该英语单词我们就可以找到该中文,这个就是键值对。
我们先来看看文档是如何介绍set容器的
那么文档里面说的是什么呢?
1.set是按照一定次数存储元素的容器(set默认按升序的规则进行排序)
2.在set只有一个value,value就是key,类型是T,并且每一个value都是唯一的。
3.在内部,集合中的元素总是按照其内部比较对象所指示的特定的严格弱排序标准进行排序
4.set容器通过key访问元素效率吗比unordered_set慢,
5.set底层是二叉搜索树(红黑树)
set的使用
set使用首选需要展开STL库和包头文件
#include <set>
using namespace std;
set的模板参数列表
set定义
set<类型名> 变量名;
set里面类型可以是任意的类型
set只能用双向迭代器进行访问(范围for底层也是迭代器)
//迭代器遍历set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;
set范围for遍历
我们知道范围fior底层是由迭代器支持的
//范围for遍历
for (auto kv : s)
{cout << kv << " ";
}
cout << endl;
set常用的成员函数接口
set插入数据
void test_set()
{//插入数据set<int> s;s.insert(3);s.insert(1);s.insert(2);s.insert(5);s.insert(4);
}
我们再来看看set里面数据能不能修改和set插入相同的数据会怎么样
直接就报错了,所以set里面的数据是不能修改的
我们看看插入相同数据会怎么样
void test_set()
{//插入数据set<int> s;s.insert(3);s.insert(1);s.insert(2);s.insert(5);s.insert(4);s.insert(4);s.insert(5);s.insert(3);//迭代器遍历set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;
}
正常运行,只是相同数据只会输出一次。
set交换元素
set<类型名>类型只能和set<类型名>类型的对象进行交换元素,必须是相同类型
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);set<int> s2;s2.insert(6);s2.insert(10);s2.insert(8);s2.insert(9);s2.insert(7);//范围for遍历for (auto kv : s1){cout << "s1:" << kv << " ";}cout << endl;for (auto kv : s2){cout << "s2:" << kv << " ";}cout << endl;//表示把s1中元素和s2的元素进行交换s1.swap(s2);//范围for遍历for (auto kv : s1){cout <<"s1:"<< kv << " ";}cout << endl;for (auto kv : s2){cout <<"s2:"<< kv << " ";}cout << endl;
}
不同类型进行交换元素
{//插入数据set<int> s1;s1.insert(3);set<string> s2;s2.insert("6");
}
判断set是否为空
如果为空返回true,不为空返回false
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);cout << s1.empty() << endl;
}
返回set中有效元素
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);cout << s1.size() << endl;
}
统计set中值为x的元素个数
只要是在set中的元素,只会出现一次,利用这个性质,可以使用set进行去掉重复的数据
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);//查找s1中值为4的元素个数int count = s1.count(4);cout << count << endl;
}
set中key的查找
find查找元素 ,找到了就返回该元素的位置(返回类型是一个iterator类型),找不到返回一个指向end()的迭代器(end()是指向最后一个key的下一个位置)
set查找元素返回的是该元素所在的位置
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);//查找元素1所在的位置auto e = s1.find(1);cout << *e << endl;
}
set删除元素
erase通过迭代器删除单个元素,找到了就删除该元素,并返回被删除的元素的下一个元素的位置
erase 通过键值进行删除元素,如果删除成功返回1,删除失败返回0
erase删除一个范围内的元素,删除成功返回被删除元素的最后一个元素的下一个元素的位置
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);s1.erase(3);//范围for遍历for (auto kv : s1){cout << kv << " ";}
}
set元素清空
void test_set()
{//插入数据set<int> s1;s1.insert(3);s1.insert(1);s1.insert(2);s1.insert(5);s1.insert(4);s1.insert(4);s1.insert(5);s1.insert(3);s1.clear();//范围for遍历for (auto kv : s1){cout << kv << " ";}
}
总结:
这篇博客分享了关联容器和序列容器区别,还有键值对定义,还有set容器特点和和set容器的使用