STL-----set容器的操作以及pair

#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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章