#include<iostream>
#include<algorithm>
#include<list>
#include<string>
#include<set>
using namespace std;
//使用set或者multiset的頭文件都是se
//set的基本概念:
/*
Set的特性是。所有元素都會根據元素的鍵值自動被排序。(關聯式容器自動排好序,序列式容器按插入順序存放)
Set的元素不像map那樣可以同時擁有實值和鍵值,set的元素即是鍵值又是實值。Set不允許兩個元素有相同的鍵值。
我們可以通過set的迭代器改變set元素的值嗎?
不行,因爲set元素值就是其鍵值,關係到set元素的排序規則。如果任意改變set元素值,會嚴重破壞set組織。
換句話說,set的iterator是一種const_iterator.
set擁有和list某些相同的性質,當對容器中的元素進行插入操作或者刪除操作的時候,操作之前所有的迭代器,
在操作完成之後依然有效,被刪除的那個元素的迭代器必然是一個例外。
*/
//multiset容器基本概念:
/*
multiset特性及用法和set完全相同,唯一的差別在於它允許鍵值重複。
set和multiset的底層實現是紅黑樹,紅黑樹爲平衡二叉樹的一種。
*/
/*
set構造函數
set<T> st;//set默認構造函數:
mulitset<T> mst; //multiset默認構造函數:
set(const set &st);//拷貝構造函數
*/
/*
set賦值操作
set& operator=(const set &st);//重載等號操作符
swap(st);//交換兩個集合容器
*/
/*
set插入和刪除操作
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//刪除pos迭代器所指的元素,返回下一個元素的迭代器。
erase(beg, end);//刪除區間[beg,end)的所有元素 ,返回下一個元素的迭代器。
erase(elem);//刪除容器中值爲elem的元素。
*/
void printSet(const set<int> &s)
{
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set<int> s1;
s1.insert(5);
s1.insert(1);
s1.insert(9);
s1.insert(3);
s1.insert(7);
printSet(s1);
//size函數:
if (!s1.size()) {
cout << "s1爲空" << endl;
}
else {
cout << "s1不爲空" << endl;
}
//刪除操作:
s1.erase(s1.begin());//還剩3.5.7.9
printSet(s1);
s1.erase(3);//5.7.9,刪除這個數;
printSet(s1);
}
/*
set查找操作
find(key);//查找鍵key是否存在,若存在,返回該鍵的元素的迭代器;若不存在,返回set.end();
count(key);//查找鍵key的元素個數
lower_bound(keyElem);//返回第一個key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一個key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key與keyElem相等的上下限的兩個迭代器。
*/
void test02()
{
//對於set,沒有value和key之分;key==value;
set<int> s1;
s1.insert(5);
s1.insert(1);
s1.insert(9);
s1.insert(3);
s1.insert(7);
//查找操作:
set<int>::iterator pos = s1.find(3);//在set中查找3這個數;
if (pos != s1.end()) {
cout << "找到了這個數,這個數是:" << *pos << endl;
}
else {
cout << "沒找到" << endl;
}
pos = s1.find(2);//在set中查找2這個數;
if (pos != s1.end()) {
cout << "找到了這個數,這個數是:" << *pos << endl;
}
else {
cout << "沒找到" << endl;
}
//count(key);//查找鍵key的元素個數
//對於set而言,結果就是0或1;
int num = s1.count(1);
cout << "1的個數爲: " << num << endl;//輸出1
num = s1.count(2);
cout << "2的個數爲: " << num << endl;//輸出0
//lower_bound(keyElem);//返回第一個key>=keyElem元素的迭代器。
set<int>::iterator it = s1.lower_bound(3);
if (it != s1.end()) {
cout << "第一個>=3的元素是: " << *it << endl;
}
else {
cout << "未找到" << endl;
}
//upper_bound(keyElem);//返回第一個key>keyElem元素的迭代器。
set<int>::iterator it_1 = s1.upper_bound(3);
if (it_1 != s1.end()) {
cout << "第一個>3的元素是: " << *it_1 << endl;
}
else {
cout << "未找到" << endl;
}
//equal_range(keyElem);//返回容器中key與keyElem相等的上下限的兩個迭代器。
//上下限,一個是lower_bound,一個是upper_bound;
//返回值爲:_NODISCARD _Paircc
//using _Paircc = pair<const_iterator, const_iterator>;
//pair;
pair<set<int>::iterator, set<int>::iterator> ret=s1.equal_range(3);
//獲取第一個值:
if (ret.first == s1.lower_bound(3)) {
cout << "找到了下限:" << *(ret.first) << endl;
}
else {
cout << "沒有找到下限" << endl;
}
if (ret.second == s1.upper_bound(3)) {
cout << "找到了上限:" << *(ret.second) << endl;
}
else {
cout << "沒有找到上限" << endl;
}
}
//補充:對組的概念:
/*
對組(pair)將一對值組合成一個值,這一對值可以具有不同的數據類型,兩個值可以分別用pair的兩個公有屬性first和second訪問。
類模板:template <class T1, class T2> struct pair.
*/
void test03()
{
//創建方式一:
pair<string, int> P1 ("Tom", 100);
//取值:
cout << (P1.first)<< endl;
cout << (P1.second) << endl;
//與上面不同,上面的pair創建的是迭代器(指針);
//創建方式二:
pair<string, int>p2 = make_pair("Jerry", 99);
cout << p2.first << endl;
cout << p2.second << endl;
}
//set不允許插入重複的key值:
//multiset允許插入重複值:
void test04()
{
set<int> s;
s.insert(10);
s.insert(10);
printSet(s);//可以編譯成功並運行,只是顯示的只有一個10;
//insert的源碼:
//_Pairib insert(value_type&& _Val)
//using _Pairib = pair<iterator, bool>;
//bool表示插入是否成功;
//有以下:
set<int> s2;
pair<set<int>::iterator, bool>ret = s2.insert(10);
if (ret.second) {
cout << "插入成功" << endl;
}
else {
cout << "插入失敗" << endl;
}
//插入成功
printSet(s2);
ret = s2.insert(10);
if (ret.second) {
cout << "插入成功" << endl;
}
else {
cout << "插入失敗" << endl;
}
//插入失敗
printSet(s2);
ret = s2.insert(20);
if (ret.second) {
cout << "插入成功" << endl;
}
else {
cout << "插入失敗" << endl;
}
//插入成功
printSet(s2);
}
//指定set的排序規則:
//仿函數:
//函數不能做類型,class可以做類型;
class myCompare
{
public:
//重載():
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void printSet_2(const set<int ,myCompare> &s)
{
for (set<int, myCompare>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//set排序:
void test05()
{
set<int> s1;
s1.insert(5);
s1.insert(1);
s1.insert(9);
s1.insert(3);
s1.insert(7);
printSet(s1);
//從小到大排序;
//從大到小排序:
//set在數據插入後不允許改變,所以只能在插入之前確定排序順序;
set<int, myCompare> s2;
s2.insert(5);
s2.insert(1);
s2.insert(9);
s2.insert(3);
s2.insert(7);
printSet_2(s2);
}
//set插入自定義數據類型:
class Person
{
public:
Person(string name,int age) :m_Name(name),m_Age(age){}
string m_Name;
int m_Age;
};
class myCompare_2
{
public:
bool operator()(const Person &p1,const Person &p2)
{
return p1.m_Age > p2.m_Age;
}
};
void test06()
{
Person p1("asdasd", 100);
Person p2("asd", 12130);
Person p3("asd\sdasd", 140);
Person p4("asdsadasdasd", 2340);
set<Person,myCompare_2> s;
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
//打印:
for (set<Person, myCompare_2>::iterator it = s.begin(); it != s.end(); it++) {
cout << "姓名是:" << it->m_Name << " 年齡是:" << it->m_Age << endl;
}
}
int main()
{
test01();
test02();
test03();
test04();
test05();
test06();
system("pause");
return 0;
}