(C++基础随笔) 06 C++ STL

STL概况

STL(Standard Template Library,标准模板库)是C++针对数据结构和算法提出的一套标准

广义上分为:

容器(container)、算法(algorithm)、迭代器(iterator)

容器和算法之间通过迭代器衔接

STL六大组件

容器、算法、迭代器、仿函数、适配器、空间配置器

  • 容器,各种数据结构,如vector、list、deque、set、map
  • 算法,如sort、find、copy、for_each
  • 迭代器,用来衔接容器和算法
  • 仿函数,行为类似函数,可以用来作为算法的某种策略(就是重载小括号()
  • 适配器,用于修饰容器、仿函数或迭代器的东西
  • 空间适配器,负责空间的配置和管理

容器

分为序列式容器和关联式容器两种

序列式容器:强调值的排序,序列式容器中的每个元素都有固定的位置

关联式容器:二叉树结构,没有严格的位置

算法

分为质变算法和非质变算法

质变算法:运算期间改变区间内元素(如插入拷贝删除)

非质变算法:不改变(如查找遍历)

迭代器

每个容器都有自己专属的迭代器

类似指针

种类功能支持运算
输入迭代器只读访问只读++、==、!=
输出迭代器只写访问只写++
前向迭代器读写,向前推进读写++、==、!=
双向迭代器读写,向前向后都行读写++、–
随机访问迭代器读写,可以跳跃+3+4+5都行,功能最强读写++、–、[n]、-n、<、<=、>、>=

常用双向迭代器和随机访问迭代器

Vector的迭代

#include <iostream>
#include<vector>
#include<algorithm>//标准算法库

using namespace std;

void myPrint(int val) {
	cout << val << endl;
}

void test01() {
	//初始化了一个vector,实际上是int类型的数组
	vector<int> v;
	//向容器插入数据
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	
	//第一种遍历
	//通过vector的迭代器遍历数组
	vector<int>::iterator itBegin = v.begin();// v.begin()指向的是容器中起始元素
	vector<int>::iterator itEnd = v.end();//同理,注意,v.end()指向的是容器中最后一个元素的下一个位置
	while (itBegin != itEnd) {
		cout << *itBegin << endl;//跟指针的写法一模一样
		itBegin++;
	}


	//第二种遍历
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << endl;
	}


	//第三种遍历,利用STL提供的for_each
	for_each(v.begin(), v.end(), myPrint);//这里传入函数名,回调了myPrint


}

Vector存放自定义数据类型

存放的对象

class Person {
public:
	Person(string name,int age) {
		this->m_name = name;
		this->m_age = age;
	}

	string m_name;
	int m_age;
};

void myprint(Person& p) {
	cout << p.m_name << "  " << p.m_age << endl;
}

void test01() {
	vector<Person> v;
	Person p1("alex", 20);
	Person p2("jim", 16);
	Person p3("peter", 34);
	Person p4("king", 26);
	Person p5("gog", 66);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);

	//遍历数据
	for (vector<Person>::iterator it = v.begin(); it < v.end(); it++) {
		//cout << (*it).m_name << "  " << (*it).m_age << endl;
        cout << it->m_name << "  " << it->m_age << endl;
	}

	for_each (v.begin(), v.end(), myprint);
}

存放的是指针

void test02() {
	//当vector存放的是Person的指针
	vector<Person *> v;
	Person p1("alex", 20);
	Person p2("jim", 16);
	Person p3("peter", 34);
	Person p4("king", 26);
	Person p5("gog", 66);
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);
	v.push_back(&p5);

	//遍历数据
	for (vector<Person *>::iterator it = v.begin(); it < v.end(); it++) {
		cout << (*it)->m_name << "  " << (*it)->m_age << endl;//尖括号里是什么类型,it就是指向这个类型的指针
	}
}

Vector中嵌套容器

void myloop(vector<int> &v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << endl;
	}
}

void test01() {
	vector<int> v1;
	vector<vector<int>> v2;
	//初始化v1
	for (int i = 0; i < 5; i++) {
		v1.push_back(i);
	}
	//初始化v2
	for (int i = 0; i < 2; i++) {
		v2.push_back(v1);//v2里存放了两个v1
	}
	
	for_each(v2.begin(), v2.end(), myloop);
}

其中,遍历外层vector使用了for_each,遍历内层vector使用了for

string容器

本质

string是c++风格的字符串,本质是一个类

  • char*是一个指针
  • string是一个类,类内部封装了char*,管理这个字符串,是一个char*类型的容器

特点

string封装了如find、copy、delete、replace、insert的成员方法

不用担心内存越界

构造函数

  • string() 空的string容器
  • string(const char* s ) 用字符串s初始化
  • string(const string& str) 用另一个string容器初始化
  • string(int n,char c) 用n个字符初始化
void test01() {
	string s1;

	const char* str = "helloworld";
	string s2(str);
	cout << "s2   " << s2 << endl;

	string s3(s2);
	cout << "s3   " << s3 << endl;

	string s4(10, '0');
	cout << "s4   " << s4 << endl;

}

string容器的赋值

在这里插入图片描述

assign有妙用

string容器的字符串拼接

在这里插入图片描述

append有妙用

string容器的字符串查找和替换

  • find查找是从左往右,rfind是从右往左
  • find找到字符串后返回第一个字符位置,找不到返回-1
  • replace是指定从哪个位置起,多少个字符,替换成什么样的字符串
    在这里插入图片描述

string容器的字符串比较

原理

将字符串转换为ASCII计算

在这里插入图片描述

string容器的字符串字符存取

  • 重载中括号[]
  • at()方法

在这里插入图片描述

string容器的字符串插入和删除

插入和删除都是从下标0开始的

在这里插入图片描述

Vector容器

非常类似数组,又称单端数组

可以动态扩展,动态扩展不是在原空间向后扩展,而是开辟新空间,拷贝源数据,释放原空间

Vector的迭代器是支持随机访问的迭代器

vector的构造

在这里插入图片描述

void myPrint(int val) {
	cout << val << " ";
}

void test01() {
	//用10个1初始化vector
	vector<int> v1(10,1);
	for_each(v1.begin(), v1.end(), myPrint);
	cout << endl;

	//用区间初始化
	vector<int> v2(v1.begin(), v1.end());//实际上和v1相同
	for_each(v2.begin(), v2.end(), myPrint);
	cout << endl;

	//拷贝构造
	vector<int> v3(v2);
	for_each(v3.begin(), v3.end(), myPrint);
	cout << endl;
	
}

vector的赋值

在这里插入图片描述

//=赋值
for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++) {
	*it = 2;
}

//assign赋值
v3.assign(5, 3);//assign会改变原容器的大小

vector的容量和大小

在这里插入图片描述

vector的插入删除

在这里插入图片描述

注意

insert和erase都要求传入的是一个迭代器,而不是index,迭代器也可以直接进行加法运算

void test01() {
	vector<int> v(5, 1);
	v.insert(v.begin() + 2, 100);
	for_each(v.begin(), v.end(), myPrint);
}

vector容器互换

在这里插入图片描述

在这里插入图片描述

vector数据存取

在这里插入图片描述

vector预留空间

在这里插入图片描述

void test01() {
	vector<int> v;
	v.reserve(100000);
    
	int num = 0;
	int* p = NULL;
	for (int i = 0; i < 100000; i++) {
		v.push_back(i);
		if (p != &v[0]) {
			p = &v[0];
			num++;
		}
	}
	cout << num << endl;
}

deque容器

双端数组

对比Vector

  • vector对于头部的插入删除效率低,数据量越大效率越低
  • vector对内部元素的访问比deque快

在这里插入图片描述

push_front()、pop_front()

push_back()、pop_back()

void printDeque(deque<int>&d) {
	for (deque<int>::iterator it = d.begin(); it != d.end(); it++) {
		cout << *it << endl;
	}
}

//通常,为了放置在引用对象的过程中修改了对象的属性,使用const_iterator
void printDeque2(const deque<int>& d) {
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
		//*it = 100;//const就不能改变属性了
		cout << *it << endl;
	}
}


void test01() {
	deque<int> d1;
	for (int i = 0; i < 5; i++) {
		d1.push_back(i);
	}
	printDeque(d1);
	printDeque2(d1);
}

deque构造函数

在这里插入图片描述

deque赋值

在这里插入图片描述

deque插入和删除

在这里插入图片描述

deque数据存取

在这里插入图片描述

deque排序

在这里插入图片描述

案例:评委打分

需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w97pKPvZ-1649417078037)(file:///C:\Users\wyh\Documents\Tencent Files\309747278\Image\C2C\49B496FCFE5C356B30718F548E552DB2.png)]

如果想要同时改变形参和实参,就需要用引用(&)的方式传入数据

实现

class Person {
public:
	Person(char name, int score=0) {
		this->m_name = name;
		this->m_score = score;
	}

	char m_name;
	int m_score;
};

void printPerson(Person &p) {
	cout << "name: " << p.m_name << "  " << "score: " << p.m_score;
}

void test01() {
	//随机数种子
	srand((unsigned int)time(NULL));

	//初始化5个选手
	vector<Person> pList;

	string sName = "ABCDE";
	for (int i = 0; i < 5; i++) {
		Person p(sName[i]);
		pList.push_back(p);
	}

	for (vector<Person>::iterator it = pList.begin(); it != pList.end(); it++) {
		//10名评委打分
		deque<int> pScore;
		for (int j = 0; j < 10; j++) {
			int score = rand() % 41 + 60;
			pScore.push_back(score);
		}

		//掐头去尾,计算平均分,绑定到选手
		pScore.pop_front();
		pScore.pop_back();

		int sum = 0;
		for (deque<int>::iterator it2 = pScore.begin(); it2 != pScore.end(); it2++) {
			sum += *it2;
		}
		int avg = sum / pScore.size();

		(*it).m_score = avg;
	}

	for (vector<Person>::iterator it = pList.begin(); it != pList.end(); it++) {
		cout << "name:  " << (*it).m_name << "  score:  " << (*it).m_score << endl;
	}
}

Stack容器

栈没有遍历!

class Person {
public:
	Person(char name, int score=0) {
		this->m_name = name;
		this->m_score = score;
	}

	char m_name;
	int m_score;
};

void printPerson(Person &p) {
	cout << "name: " << p.m_name << "  " << "score: " << p.m_score << endl;
}

void test01() {
	stack<Person> sta;

	//初始化5名乘客
	string pName = "ABCDE";
	for (int i = 0; i < 5; i++) {
		Person p(pName[i], 0);
		//入栈
		sta.push(p);
	}

	//只要栈不为空,就读取栈顶并出栈
	while (!sta.empty()) {
		Person p=sta.top();
		printPerson(p);
		sta.pop();
	}
}

Queue容器

class Person {
public:
	Person(char name, int score=0) {
		this->m_name = name;
		this->m_score = score;
	}

	char m_name;
	int m_score;
};

void printPerson(Person& p) {
	cout << "name: " << p.m_name << "  " << "score: " << p.m_score << endl;
}

void test01() {
	queue<Person> que;

	string pName = "ABCDE";
	for (int i = 0; i < 5; i++) {
		Person p(pName[i], 0);
		que.push(p);
	}

	while (!que.empty()) {
		Person p=que.front();
		printPerson(p);
		que.pop();
	}

}

List容器

链表将数据链式存储

由一系列结点组成,结点包括数据域和指针域

STL的链表是双向循环链表

优缺点

优点:可以对任意位置快速插入和删除

缺点:遍历速度没有数组快,占用空间比数组大

因为链表是链式存储,所以链表的迭代器只支持前移和后移

链表的插入和删除不会让原迭代器失效

构造函数

void printList(const list<int> &l) {
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++) {
		cout << " " << *it << " ";
	}
	cout << endl;
}

void test01() {
	list<int> l1;
	for (int i = 0; i < 5; i++) {
		l1.push_back(i);
	}

	list<int> l2(l1.begin(), l1.end());
	list<int> l3(l1);
	list<int> l4(10, 200);
	printList(l1);
	printList(l2);
	printList(l3);
	printList(l4);

}

赋值和交换

在这里插入图片描述

大小操作

在这里插入图片描述

数据存取

在这里插入图片描述

反转和排序

在这里插入图片描述

所有不支持随机访问的容器,都不能调用标准算法库了的算法

void printList(const list<int> &l) {
	for (list<int>::const_iterator it = l.begin(); it != l.end(); it++) {
		cout << " " << *it << " ";
	}
	cout << endl;
}

bool myCompare(int val1, int val2) {
	return val1 > val2;
}

void test01() {
	list<int> l1;
	l1.push_back(20);
	l1.push_back(40);
	l1.push_back(30);
	l1.push_back(10);
	l1.push_back(50);

	cout << "排序前:  " << endl;
	printList(l1);

	//所有不支持随机访问的容器,都不能调用标准算法库了的算法
	//但是自己会内部实现各种算法
	l1.sort();
	cout << "排序后:  " << endl;
	printList(l1);

	//降序排列
	l1.sort(myCompare);
	printList(l1);

}

案例:List排序

class Person {
public:
	Person(string name, int age,int height) {
		this->m_name = name;
		this->m_age = age;
		this->m_height = height;
	}

	string m_name;
	int m_age;
	int m_height;
};

void printPerson(Person& p) {
	cout << "name: " << p.m_name << "  " << "  age: " << p.m_age <<"  height:  "<<p.m_height<< endl;
}

bool comparePerson(Person &p1,Person &p2) {
	if (p1.m_age == p2.m_age) {
		//如果年龄相同,按照身高降序
		return p1.m_height > p2.m_height;
	}
	return p1.m_age < p2.m_age;
}


void test01() {
	//排序案例:按照年龄升序,如果年龄相同,按照身高降序
	Person p1("alex", 22, 187);
	Person p2("jim", 24, 178);
	Person p3("amy", 21, 165);
	Person p4("jerry", 24, 198);
	Person p5("fred", 19, 180);

	list<Person> lp;
	lp.push_back(p1);
	lp.push_back(p2);
	lp.push_back(p3);
	lp.push_back(p4);
	lp.push_back(p5);

	//排序前
	cout << "排序前:  " << endl;
	for (list<Person>::iterator it = lp.begin(); it != lp.end(); it++) {
		printPerson((*it));
	}

	lp.sort(comparePerson);//这里要传入一个回调函数,必须是bool类型,以两个Person类的形参来指定规则

	//排序后
	cout << "排序后:  " << endl;
	for (list<Person>::iterator it = lp.begin(); it != lp.end(); it++) {
		printPerson((*it));
	}
}

Set/Multiset容器

特点

所有元素会在插入时自动排序插入只有insert

本质

关联式容器,底层结构是二叉树实现的

区别

  • set不允许重复元素(不报错,但是不会插入)
  • multiset允许

因为set的insert方法会返回一个是否插入成功的bool

构造和赋值

在这里插入图片描述

大小和交换

在这里插入图片描述

插入和删除

在这里插入图片描述

set和multiset区别

在这里插入图片描述

Set容器排序

利用仿函数

//仿函数的类型
//具有类型“const MyCompare”的表达式会丢失一些 const - volatile 限定符以调用...
class MyCompare {
public:
	bool operator() (int v1,int v2) const//仿函数要加上const限定
	{
		return v1 > v2;
	}
};

void printSet2(set<int, MyCompare>& s1) {
	for (set<int, MyCompare>::iterator it = s1.begin(); it != s1.end(); it++) {
		cout << *it << endl;
	}
}

//set容器排序
void test01() {
	set<int, MyCompare> s1;
	s1.insert(20);
	s1.insert(10);
	s1.insert(50);
	s1.insert(70);
	s1.insert(30);

	printSet2(s1);
}

Set容器排序(自定义数据类型)

class Person {
public:
	Person(string name, int age) {
		this->pName = name;
		this->pAge = age;
	}

	void printPerson() {
		cout << "name:  " << this->pName << "  " << "age:  " << this->pAge << endl;
	}

	string pName;
	int pAge;

};

//自定义的数据类型通常都要实现仿函数
class MyCompare {
public:
	bool operator() (const Person& p1,const Person& p2) const//仿函数要加上const限定
	{
		return p1.pAge > p2.pAge;
	}
};


//set容器排序(自定义类型)
void test01() {
	set<Person, MyCompare> s1;
	Person p1("alex", 24);
	Person p2("gog", 56);
	s1.insert(p1);
	s1.insert(p2);

	for (set<Person, MyCompare>::iterator it = s1.begin(); it != s1.end(); it++) {
		cout << (*it).pName<<"  "<<(*it).pAge << endl;
	}
}

Pair容器

  • 不需要引用头文件
  • 可嵌套使用
    在这里插入图片描述
void test01() {
	pair<int, string> p1(1, "first");
	pair<int, string> p2(2, "second");
	pair<pair<int, string>, pair<int, string>> p(p1, p2);
	
	//取出第一个pair
	cout << p.first.first << "  " << p.first.second << endl;
	cout << p.second.first << "  " << p.second.second << endl;
}

map/multimap容器

简介

  • map中所有元素都是pair
  • pair<key,value>
  • 所有元素都会根据key自动排序

本质

关联性容器,底层是二叉树

优点

按key查找高效

map和multimap区别

  • map不允许重复
  • multimap允许

构造和赋值

  • 构造时<key,value>
  • insert(pair<>)
    在这里插入图片描述
class Person {
public:
	Person(string name, int age) {
		this->pName = name;
		this->pAge = age;
	}

	void printPerson() {
		cout << "name:  " << this->pName << "  " << "age:  " << this->pAge << endl;
	}

	string pName;
	int pAge;

};

//自定义的数据类型通常都要实现仿函数
class MyCompare {
public:
	bool operator() (const Person& p1,const Person& p2) const//仿函数要加上const限定
	{
		return p1.pAge > p2.pAge;
	}
};

void printMap(map<int, Person> &m1) {

	for (map<int, Person>::iterator it = m1.begin(); it != m1.end(); it++) {
		(*it).second.printPerson();
	}
}


//set容器排序(自定义类型)
void test01() {
	map<int, Person> m1;
	Person p1("alex", 24);
	pair<int, Person> pair1= make_pair(1, p1);
	Person p2("gog", 56);
	pair<int, Person> pair2 = make_pair(2, p2);
	m1.insert(pair1);
	m1.insert(pair2);

	printMap(m1);

}

大小和交换

在这里插入图片描述

插入和删除

在这里插入图片描述

查找和统计

在这里插入图片描述

map排序

class Person {
public:
	Person(string name, int age) {
		this->pName = name;
		this->pAge = age;
	}

	void printPerson() {
		cout << "name:  " << this->pName << "  " << "age:  " << this->pAge << endl;
	}

	string pName;
	int pAge;

};

//自定义的数据类型通常都要实现仿函数
class MyCompare {
public:
	bool operator() (const int& k1,const int& k2) const//仿函数要加上const限定
	{
		return k1>k2;
	}
};

void printMap(map<int, Person, MyCompare> &m1) {

	for (map<int, Person, MyCompare>::iterator it = m1.begin(); it != m1.end(); it++) {
		(*it).second.printPerson();
	}
}

void printMap2(map<int, Person>& m1) {

	for (map<int, Person>::iterator it = m1.begin(); it != m1.end(); it++) {
		(*it).second.printPerson();
	}
}

//set容器排序(自定义类型)
void test01() {
	map<int, Person,MyCompare> m1;
	//map<int, Person> m1;
	Person p1("alex", 24);
	pair<int, Person> pair1= make_pair(1, p1);
	Person p2("gog", 56);
	pair<int, Person> pair2 = make_pair(2, p2);
	Person p3("yum", 12);
	pair<int, Person> pair3 = make_pair(3, p3);
	Person p4("owen", 17);
	pair<int, Person> pair4 = make_pair(4, p4);
	m1.insert(pair1);
	m1.insert(pair2);
	m1.insert(pair3);
	m1.insert(pair4);

	printMap(m1);

}

STL案例-员工分组

需求

在这里插入图片描述

代码

#include <iostream>
#include<algorithm>
#include<vector>
#include<map>


#define CEHUA 0
#define MEISHU 1
#define YANFA 2

using namespace std;


class Person {
public:
	Person() {}
	Person(string name, int salary) {
		this->pName = name;
		this->pSalary = salary;
	}

	void printPerson() {
		cout << "name:  " << this->pName << "  " << "salary:  " << this->pSalary << endl;
	}

	string pName;
	int pSalary;

};

void createWorker(vector<Person> &pList) {
	string nameString = "ABCDEFGHIJ";
	for (int i = 0; i < nameString.size(); i++) {
		Person p;
		p.pName = "员工";
		p.pName += nameString[i];

		p.pSalary = rand() % 10000 + 10000;

		pList.push_back(p);
	}
}

void printVector(vector<Person> &v) {
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
		(*it).printPerson();
	}
}

void setGroup(vector<Person> &v,multimap<int,Person> &mWorker) {
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) {
		//产生一个部门的随机号
		int deptId = rand() % 3;//0 1 2
		//将员工插入到分组中
		mWorker.insert(make_pair(deptId, (*it)));
	}
}

void showWorker(multimap<int,Person> &mWorker) {
	for (multimap<int, Person>::iterator it = mWorker.begin(); it != mWorker.end(); it++) {
		//*it解出来是一个个pair
		cout << "部门:" << (*it).first << "  ";
		(*it).second.printPerson();
	}
}

void showDeptWorker(multimap<int, Person>& m, multimap<int, Person>::iterator& pos, int count,int index) {
	for (; pos != m.end() && index < count; pos++, index++) {
		cout << "部门:" << (*pos).first << "  ";
		(*pos).second.printPerson();
	}
}

//set容器排序(自定义类型)
void test01() {
	//创建10个员工
	vector<Person> pList;
	createWorker(pList);

	测试是否添加成功
	//printVector(pList);

	//遍历vector容器,取出每个员工,进行随机分组
	//分组后,员工编号作为key,具体员工作为value,放入multimap容器中
	multimap<int, Person> mWorker;
	setGroup(pList,mWorker);
	显示所有员工信息
	//showWorker(mWorker);

	//分部门显示员工信息
	multimap<int, Person>::iterator pos = mWorker.find(CEHUA);
	int count = mWorker.count(CEHUA);
	int index = 0;
	showDeptWorker(mWorker, pos, count, index);
	

}

int main() {
	srand((unsigned int)time(NULL));//每次都生成新的随机数种子

	test01();

	system("pause");
	return 0;
}

STL函数对象

讲的就是仿函数,重载了()

在这里插入图片描述

class MyAdd {
public:
	int operator()(int v1,int v2){
		this->sum= v1 + v2;
		return this->sum;
	}

private:
	int sum;
};

class MyPrint {
public:
	MyPrint() {
		this->count = 0;
	}
	void operator()(string s) {
		cout << s << endl;
		this->count++;
	}

	int count;
};

void doPrint(MyPrint &mp,string s) {
	mp(s);
}

void test01() {
	MyAdd myAdd;
	//仿函数可以像普通函数一样调用
	cout << myAdd(10, 10) << endl;
}

void test02() {
	//仿函数跟普通函数不同,仿函数可以有自己的状态,如可以统计自己被调用了多少次
	MyPrint mp;
	mp("hello world");
	mp("hello world");
	mp("hello world");
	mp("hello world");
	mp("hello world");
	cout << "执行了: " << mp.count << "次" << endl;
}

void test03() {
	//仿函数对象可以作为参数传递
	MyPrint mp;
	doPrint(mp, "hello alex");
}

谓词

返回bool类型的仿函数被称为谓词

在这里插入图片描述

一元谓词

重载()接收一个参数的时候

//一元谓词
class GreaterFive {
public:
	//由于遍历期间会取出来每一个数据,这里要挨个接受,所以要指定形参v1
	bool operator()(int v1) {
		return v1 > 5;
	}
};

void test01() {
	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}

	//查找v中大于5的元素
	//GreaterFive()是一个匿名的对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
	for (it; it < v.end(); it++) {
		if (it == v.end()) {
			cout << "未找到" << endl;
		}
		else
		{
			cout << *it << endl;
		}
	}
}

二元谓词

重载()接收两个参数的时候

//二元谓词
class MyCompare {
public:
	bool operator()(int v1,int v2) {
		return v1 > v2;
	}
};

void test01() {
	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	
	//sort默认是升序,这里要用谓词实现降序,这里的MyCompare()同样是匿名对象
	sort(v.begin(),v.end(),MyCompare());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

STL内建函数对象

在这里插入图片描述

三类

  • 算数仿函数
  • 关系仿函数
  • 逻辑仿函数

算数仿函数

在这里插入图片描述

#include<functional>

void test01() {
	//一元,negate
	negate<int> n;
	cout << n(10) << endl;

	//二元,plus
	plus<int> pl;
	cout<<pl(10, 10) << endl;
}

关系仿函数

在这里插入图片描述

#include<functional>

void test01() {
	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}

	//调用内建的关系仿函数来实现降序排序
	sort(v.begin(), v.end(), greater<int>());

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << "  ";
	}
	cout << endl;
}

逻辑仿函数

在这里插入图片描述

#include<functional>

void test01() {
	vector<bool> v;
	v.push_back(false);
	v.push_back(true);
	v.push_back(false);
	v.push_back(true);

	for (vector<bool>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << "  ";
	}
	cout << endl;

	//利用逻辑非 取反
	vector<bool> v2;
	v2.resize(v.size());
	transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());

	for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++) {
		cout << *it << "  ";
	}
	cout << endl;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值