学习 C++STL(三)

文章详细介绍了C++STL中的set、multiset、map及multimap容器的基本概念、构造、赋值、大小、交换、插入、删除、查找、统计等操作。set和multiset的区别在于set不允许插入重复元素,而multiset可以。同时,文章展示了如何自定义排序规则以及如何使用pair和谓词。map和multimap则以键值对形式存储数据,map不允许重复键值,multimap则允许。
摘要由CSDN通过智能技术生成

set/multiset容器

基本概念:

所有元素都会在插入的时候自动被排序

本质:

属于关联式容器,底层用二叉树实现

头文件

#include<set>

在set 容器中,不可以插入重复的数据,如果插入了,也是白插,不会存储在容器中。

构造:

  • 默认构造
  • 拷贝构造

赋值:

  • = 赋值操作

大小和交换

  • size()
  • empty()
  • swap(st) 交换两个set容器

插入和删除

  • insert(elem)在容器中插入元素
  • clear()清空所有元素
  • erase(pos)删除pos迭代器所指的的数据
  • erase(beg,end) 删除区间[beg,end)的所有元素
  • erase(elem )删除容器中的elem元素

查找和统计

  • fine(key) 查找key是否存在,返回值为一个迭代器
  • count(key) 统计key元素的个数
#include<iostream>
#include<set>
using namespace std;
void printSet(set<int >& s)
{
	for (set<int>::iterator se = s.begin(); se != s.end(); se++)
	{
		cout << *se << ' ';
	}
	cout << endl;
}
void test01()
{
	set<int > s;
	set<int > s1;

	//向容器s中添加数据
	s.insert(10);
	s.insert(20);
	s.insert(30);
	s.insert(70);
	s.insert(40);
	//输出s容器
	printSet(s);
	//输出s容器大小
	cout << "容器大小为:" << s.size()<< endl;
	//向容器s1中添加数据
	s1.insert(50);
	s1.insert(60);
	s1.insert(20);
	s1.insert(36);
	s1.insert(85);
	//输出s1中的内容
	printSet(s1);

	//交换s和s1的数据元素
	s.swap(s1);
	//输出交换后的容器数据
	cout << "交换后s容器中的内容:";
	printSet(s);
	cout << "交换后s1容器中的内容:";
	printSet(s1);
	//删除操作
	cout << "删除操作:" << endl;
	//删除某个迭代器所指位置的内容
	s.erase(s.begin());
	cout << "删除s中s.begin()之后容器的内容" << endl;
	printSet(s);
	cout << "删除区间[s1.begin(),s1.end())之后容器剩余的数据" << endl;
	s1.erase(s1.begin(), s1.end());
	printSet(s1);
	//查找
	set<int>::iterator it = s.find(10);
	if (it == s.end())
	{
		cout << "数据不存在" << endl;
	}
	else {
		cout << *it << endl;
	}
	//统计元素个数
	//对于set而言,统计的结果要么是0要么是1,
	//这个主要是用于multiset,multiset中可以有重复元素
	cout << "查找36在set中出现的次数:" << s.count(36) << endl;
}
int main()
{
	test01();
}

set和multiset的区别

  • set不可以插入重复的数据,但是multiset可以
  • set插入数据时会返回先插入结果,表示是否插入成功
  • multiset不会检测数据,因此可以重复插入数据
void printMultiset(multiset<int >& s)
{
	for (multiset<int>::iterator se = s.begin(); se != s.end(); se++)
	{
		cout << *se << ' ';
	}
	cout << endl;
}
void test02()
{
	multiset<int> mul;
	mul.insert(10);
	mul.insert(10);
	mul.insert(10);
	mul.insert(10);
	printMultiset(mul);
}
int main()
{
	//test01();
	test02();
}

输出结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6qhtKykn-1673777224704)(STL%EF%BC%88%E4%B8%89%EF%BC%89%20d0181e0e0ca24c2c9e268f8a308c92cc/Untitled.png)]

pair对组的创建和使用

概念:

成对出现的数据,包括两个数据,利用对组可以返回两个数据

void test03()
{
	//第一种创建方式
	pair<string, int> stu("tom", 18);
	//第二种创建方式
	pair<string, int> st = make_pair("Alice",18);

	cout << stu.first<< ' '<< stu.second << endl;
	cout << st.first<< ' '<< st.second << endl;
}
int main()
{
	//test01();
	//test02();
	test03();
}

set容器排序

set容器默认为从小到大的排序,这里讲述怎么改变这种默认排序

利用仿函数,改变排序的规则

//利用仿函数修改set容器的规则
class Compare
{
public:
	bool operator()(int v1, int v2)const
	{
		return v1 > v2;
	}
};
void test04()
{
//规则需要在添加数据之前设置
	set<int,Compare> s;
	s.insert(12);
	s.insert(62);
	s.insert(22);
	s.insert(62);
	s.insert(6);
	s.insert(98);
	for (set<int,Compare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << ' ';
	}
}
int main()
{
	//test01();
	//test02();
	//test03();
	test04();
}

set容器添加自定义数据类型

set不能识别自定义类型的大小,需要自己设置排序规则

就需要重载operator()设置排序规则

class Dog
{
public :
	Dog(string name, int age)
	{
		this->name = name;
		this->age = age;
	}
	string name;
	int age;
};
//仿函数重载
class Compare
{
public:
	bool operator()(const Dog d1, const Dog d2)const
	{
		return d1.age > d2.age;
	}
};

void test05()
{
	set<Dog, Compare> s;
	Dog d1("小黄",2);
	Dog d2("小白",3);
	Dog d3("小蓝",1);
	Dog d4("小红",5);
	s.insert(d1);
	s.insert(d2);
	s.insert(d3);
	s.insert(d4);

	//输出
	for (set<Dog, Compare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << it->name <<' ' << it->age << endl;
	}
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	test05();
}

map/multimap容器

基本概念

  • map中所有的元素都是pair
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值(key)自动排序
  • 本质上是关联式容器,底层是用二叉树实现

优点:

  • 可以根据不同的key值找到value值

map与multimap的区别:

  • map不允许容器中有重复的key值
  • multimap允许容器中有重复的key值

构造

  • 默认构造
  • 拷贝构造

赋值

  • = 赋值
void printMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key" << it->first << '\t' << "value" << it->second << endl;
	}
}
void test06()
{
	//默认构造
	//两个参数指定key和value的类型
	map<int,int> m;

	m.insert(pair<int,int>(-1,10));
	m.insert(pair<int,int>(2,20));
	m.insert(pair<int,int>(3,30));
	m.insert(pair<int,int>(4,40));
	printMap(m);
	//拷贝构造
	map<int, int>m2 = m;
	printMap(m2);
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	test06();
}

大小和交换

  • size() 返回容器数据数目
  • empty() 容器是否为空
  • swap(ma) 交换两个容器

插入和删除

  • insert(elem) 每个元素都是对组
  • clear()清空
  • erase(pos ) 删除POS迭代器所指的数据
  • erase(beg,end) 删除区间内容
  • erase(key)删除值为key的元素
//四种插入数据方式
	//第一种
	map<int, int> m1;
	m1.insert(pair<int, int>(1, 10));

	//第二种
	m1.insert(make_pair(2, 20));

	//第三种
	m1.insert(map<int, int>::value_type(3, 30));
	printMap(m1);

	//第四种  不推荐用来插入数据
	// 可用来访问数据
	//如下,key值为4,value为40;
	m1[4] = 40;

查找和统计

  • find(key) 返回键值为key 的迭代器,如果不存在,返回end()迭代器
  • count(key) 对于map只能返回0或1,multimap返回的值可能会大于1

排序

默认顺序根据key值从小到大排序

利用仿函数,改变排序规则

//修改排序规则
class MyCompare
{
public:
	bool operator()(int v1,int v2)const
	{
		return v1 > v2;
	}
};

void printMap2(map<int, int,MyCompare>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key" << ' ' << it->first << '\t' << "value" << ' ' << it->second << endl;
	}
}
void test07()
{
	map<int, int,MyCompare> m;

	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(4, 40));
	printMap2(m);
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	test07();
}

函数对象

概念:

重载了函数调用操作符的类,其对象通常称为函数对象

函数对象使用重载的()时,行为类似函数调用,也叫仿函数

本质:

本质是一个类,不是一个函数

特点:

  • 函数对象在使用时,可以像普通函数那样调用 ,可以有参数,也可以有返回值
  • 函数对象可以有自己的状态
  • 函数对象可以作为参数传递
//可以像普通函数调用
class Sum
{
public:
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};
void test08()
{
	Sum sum;
	int a = sum(10, 23);
	
	cout << a;
}

int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	test08();
}
//可以作为参数传递
class Print
{
public:
	void operator()(string name)
	{
		cout << name << endl;
	}
};
void DoPrint(Print& P, string name)
{
	P(name);
}
void test09()
{
	Print P;
	DoPrint(P, "小黄");
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	test09();
}

谓词

概念

  • 返回bool类型的仿函数称为谓词
  • 如果operator()接受一个参数,叫做一元谓词
  • 如果operator()接受两个参数,叫做二元谓词

一元谓词案例

//查找大于10 的数字
class GraterTen
{
public :
	bool operator()(int val)
	{
		return val > 10;
	}
};
void test10()
{
	vector<int> v;
	v.push_back(23);
	v.push_back(2);
	v.push_back(3);
	v.push_back(15);
	v.push_back(16);
//find_if在vector容器中查找大于10的数值,如果找到,返回迭代器
//GraterTen()创建匿名对象,这个是用来判断数据是否大于10
	vector<int> ::iterator it = find_if(v.begin(), v.end(), GraterTen());
	cout << *it;
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	test10();

}

二元谓词案例

//改变排序规则
class compare
{
public:
	bool operator()(int val1, int val2)
	{
		return val1 > val2;
	}
};
void test11()
{
	vector<int> v;
	v.push_back(15);
	v.push_back(32);
	v.push_back(25);
	v.push_back(55);
//compare()创建匿名对象
	sort(v.begin(), v.end(), compare());
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << ' ';
	}
	cout << endl;
}
int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	//test06();
	//test07();
	//test08();
	//test09();
	//test10();
	test11();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

17丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值