42 STL

1 STL 入门

容器内放int等类型

#include<iostream>
using namespace std;
#include <vector>
#include<algorithm>

void main11() {
	vector<int> v1;	// 1 容器 把元素copy到容器中
	v1.push_back(-1);
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(3);

	// 2 迭代器:相当于指针
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
		cout << *it << endl;
	}
	// 3 算法 容器中含有3的数目
	int num1 = count(v1.begin(), v1.end(), 3);
	cout << "num1: " << num1 << endl;
}

void main() {
	
	main11();
}

容器放入类和类指针

#include<iostream>
using namespace std;
#include <vector>
#include<algorithm>

void main12() {

	Teacher t1, t2, t3;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;

	Teacher* p1, * p2, * p3;
	p1 = &t1;
	p2 = &t2;
	p3 = &t3;

	vector<Teacher> v1;
	v1.push_back(t1);
	v1.push_back(t2);
	v1.push_back(t3);

	vector<Teacher*> v2;	// 把 t1,t2,t3内存首地址放入容器
	v2.push_back(p1);
	v2.push_back(p2);
	v2.push_back(p3);


	// 2 迭代器:相当于指针
	
	for (vector<Teacher>::iterator it = v1.begin(); it != v1.end(); it++) {
		cout << it->age << endl;
	}

	for (vector<Teacher*>::iterator it = v2.begin(); it != v2.end(); it++) {
		cout << (*it)->age << endl;
	}

}

void main() {
	
	main12();
}

2 STL string 操作

1 string 初始化

#include<iostream>
#include<string>
using namespace std;

// string 初始化
void main21() {
	string s1 = "aaaaa";
	string s2("bbbb");	
	string s3 = s2;	//通过拷贝构造函数初始化s3
	string s4(10, 'a');
	cout << "s1: " << s1 << endl;
	cout << "s2: " << s2 << endl;
	cout << "s3: " << s3 << endl;
	cout << "s4: " << s4 << endl;
}

void main() {
	main21();
}

2 字符遍历

// string 遍历
void main22() {
	string s1 = "abcdefg";

	// 数组方式
	for (int i = 0; i < s1.length(); i++) {
		cout << s1[i] << " ";
	}
	cout << endl;

	// 迭代器
	for (string::iterator it = s1.begin(); it != s1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;

	//

	try
	{
		for (int i = 0; i < s1.length()+3; i++) {
			cout << s1.at(i) << " ";	// 可以抛出异常
		}
	}
	catch (...)
	{
		cout << "发生异常" << endl;
	}

	cout << "at之后..." << endl;
}

void main() {
	main22();
}

结果

a b c d e f g
a b c d e f g
a b c d e f g 发生异常
at之后...

3 字符指针和string的转换

// 字符指针和string的转换
void main23() {
	string s1 = "aaaaanbbbb";
	// string===>char*
	printf("s1: %s\n", s1.c_str());

	// char* ===>string

	
	// s1的内容拷贝到buf
	char buf[128] = { 0 };
	s1.copy(buf,3,0);	//只负责拷贝字符,不负责变为c风格字符串
	cout << "buf1: " << buf << endl;
}


void main() {
	main23();
}

4 字符串连接

// 字符串连接
void main24() {
	string s1 = "aaa";
	string s2 = "bbb";
	s1 = s1 + s2;
	cout << "s1:" << s1 << endl;

	string s3 = "333";
	string s4 = "444";
	s3.append(s4);
	cout << "s3: " << s3 << endl;
}

void main() {
	main24();
}

5 字符串查找和替换

// 字符串查找
void main25() {
	string s1 = "xd 123 xd 456 xd 789";
	// 第一次出现xd index 

	int index = s1.find("xd", 0);	// 位置下标从0开始
	cout << "index: " << index << endl;

	// 求xd出现次数,每次的下标
	int offindex = s1.find("xd", 0);
	// n_pos -1
	while (offindex != string::npos) {
		cout << "offindex: " << offindex << endl;
		offindex = offindex + 1;
		offindex = s1.find("xd",offindex);
	}
	
}

void main() {
	main25();
}

结果

index: 0
offindex: 0
offindex: 7
offindex: 14

// 字符串替换
void main25() {
	// 替换 小写改大写
	int offindex = s1.find("xd", 0);
	// n_pos -1
	while (offindex != string::npos) {
		cout << "offindex: " << offindex << endl;
		s1.replace(offindex, 2, "XD");
		offindex = offindex + 1;
		offindex = s1.find("xd", offindex);
	}
	cout << "替换后结果:" << s1 << endl;
	
	string s3 = "aaa bbb ccc";
	s3.replace(0, 3, "AAA");
	cout << "s3: " << s3 << endl;

}

void main() {
	main25();
}

结果

offindex: 0
offindex: 7
offindex: 14
替换后结果:XD 123 XD 456 XD 789
s3: AAA bbb ccc

6 区间删除和插入

#include<algorithm>
// 区间删除和插入
void main26() {
	string s1 = "hello1 hello2 hello3";
	string::iterator it = find(s1.begin(), s1.end(), 'l');
	if (it != s1.end()) {
		s1.erase(it);
	}
	cout << "s1删除后结果: " << s1 << endl;

	s1.erase(s1.begin(), s1.end());
	cout << "s1全部删除后结果: " << s1 << endl;
	cout << "s1长度: " << s1.length() << endl;

	string s2 = "BBB";
	s2.insert(0, "AAA");
	cout << "s2 : " << s2 << endl;
	s2.insert(s2.length(), "CCC");
	cout << "s2 : " << s2 << endl;
}

void main() {
	main26();
}

结果

s1删除后结果: helo1 hello2 hello3
s1全部删除后结果:
s1长度: 0
s2 : AAABBB
s2 : AAABBBCCC

7 相关算法

大小写转换

#include<algorithm>
void main27() {
	string s1 = "AAAbbb";
	// 函数的入口地址 函数对象 预定义的函数
	transform(s1.begin(), s1.end(),s1.begin(), toupper);
	cout << "s1: " << s1 << endl;
	
	string s2 = "AAAbbb";
	transform(s2.begin(), s2.end(),s2.begin(), tolower);
	cout << "s2: " << s2 << endl;
}


void main() {
	main27();
}

结果

s1: AAABBB
s2: aaabbb

3 Vector容器

vector尾部添加或移除元素比较快,但是在中部或头部插入或移除元素比较费时

头部尾部元素

#include<iostream>
#include<vector>
using namespace std;

void main31() {
	vector<int> v1;

	cout << "length: " << v1.size() << endl;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	cout << "length: " << v1.size() << endl;

	cout << "头部元素: " << v1.front() << endl;
	cout << "尾部元素:" << v1.back() << endl;
	
	// 修改头部
	// 函数返回值当左值应该返回一个引用
	v1.front() = 11;
	v1.back() = 55;

	while (v1.size() > 0) {
		cout << "尾部元素:" << v1.back() << endl;	//获取尾部元素
		v1.pop_back();	//删除尾部元素
	}

	

}

void main() {
	main31();
}

vector 初始化

// vector 初始化
void main32() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);

	vector<int> v2 = v1;	//对象初始化方法

	vector<int> v3(v1.begin(), v1.begin() + 2); //对象初始化方法

}
void main() {
	//main31();
	main32();
}

vector遍历

void printV(vector<int>& v) {
	for (int i = 0; i < v.size(); i++) {
		printf("%d ", v[i]);
	}
}
// vector 遍历
void main33() {
	vector<int> v1(10);		//提前分配好内存
	/*for (int i = 0; i < 10; i++) {
		printf("%d ", v1[i]);
	}*/
	printV(v1);
	cout << endl;
	for (int i = 0; i < 10; i++) {
		v1[i] = i + 1;
	}
	/*for (int i = 0; i < 10; i++) {
		printf("%d ", v1[i]);
	}*/
	printV(v1);

}
void main() {
	main33();
}

结果

0 0 0 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10

push_back()

void main34() {
	vector<int> v1(10);
	v1.push_back(100);
	v1.push_back(200);
	cout << "size: " << v1.size() << endl;
	printV(v1);
}

void main() {
	main34();
}

结果

size: 12
0 0 0 0 0 0 0 0 0 0 100 200

迭代器

// 迭代器
//  1 3 5
// ▲
//       ▲
//当it == v1.end()时说明遍历已经结束
// end位置在5的后面

// 迭代器的种类
void main35() {
	vector<int> v1(10);
	for (int i = 0; i < v1.size(); i++) {
		v1[i] = i + 1;
	}
	//正向遍历
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
	//逆序遍历
	for (vector<int>::reverse_iterator it = v1.rbegin(); it != v1.rend(); it++) {
		cout << *it << " ";
	}
}

void main() {
	main35();
}

结果

1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1

删除

// 删除
void main36() {
	vector<int> v1(10);
	for (int i = 0; i < v1.size(); i++) {
		v1[i] = i + 1;
	}

	// 区间删除
	v1.erase(v1.begin(), v1.begin() + 3);
	printV(v1);
	cout << endl;

	// 指定位置删除
	v1.erase(v1.begin());
	printV(v1); 
	cout << endl;

	// 根据元素值删除
	v1[1] = 2;
	v1[3] = 2;
	printV(v1);
	cout << endl;

	for (vector<int>::iterator it = v1.begin(); it != v1.end(); ) {
		if (*it == 2) {
			it = v1.erase(it);	//当删除迭代器所指向元素时,erase会让it自增,不用移动 返回一个指针
		}
		else {
			it++;
		}
	}
	printV(v1);
	cout << endl;

}

void main() {
	main36();
}

结果

4 5 6 7 8 9 10
5 6 7 8 9 10
5 2 7 2 9 10
5 7 9 10

插入

// 插入
void main37() {
	vector<int> v1(5);
	for (int i = 0; i < v1.size(); i++) {
		v1[i] = i + 1;
	}
	printV(v1);
	cout << endl;
	v1.insert(v1.begin(), 100);
	v1.insert(v1.end(), 200);
	printV(v1);
	cout << endl;
}

void main() {
	main37();
}

结果

1 2 3 4 5
100 1 2 3 4 5 200

4 deque容器(双向数组)

#include<iostream>
#include<deque>
#include<algorithm>
using namespace std;


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

void main41() {
	deque<int> d1;
	d1.push_back(1);
	d1.push_back(3);
	d1.push_back(5);

	d1.push_front(-11);
	d1.push_front(-33);
	d1.push_front(-55);

	cout << "头部元素:" << d1.front() << endl;
	cout << "尾部元素: " << d1.back() << endl;
	printD(d1);
	cout << endl;

	d1.pop_front();
	d1.pop_back();
	printD(d1);
	cout << endl;

	// 查找-33在数组下标位置
	deque<int>::iterator it = find(d1.begin(), d1.end(), -33);
	if (it != d1.end()) {
		cout << "-33的下标是" << distance(d1.begin(), it) << endl;
	}
	else {
		cout << "没有找到值为-33的下标" << endl;
	}
}

void main() {
	main41();
}

结果

头部元素:-55
尾部元素: 5
-55 -33 -11 1 3 5
-33 -11 1 3
-33的下标是0

5 Stack容器

基本数据类型

#include<iostream>
#include<stack>
using namespace std;

// 栈模型
// 栈算法 和 数据类型分离
void main51() {
	stack<int> s;
	
	// 入栈
	for (int i = 0; i < 10; i++) {
		s.push(i + 1);
	}

	cout << "栈的大小:" << s.size() << endl;

	// 出栈
	while (!s.empty()) {
		int tmp = s.top();	// 获取栈顶元素
		cout << tmp << " ";
		s.pop();	//弹出栈顶元素
	}
}

void main() {
	main51();
}

结果

栈的大小:10
10 9 8 7 6 5 4 3 2 1

//Teacher节点
class Teacher {
public:
	int age;
	char name[32];
	void printT() {
		cout << "age: " << age << endl;
	}
};
void main52() {
	Teacher t1, t2, t3;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;

	stack<Teacher> s;
	s.push(t1);
	s.push(t2);
	s.push(t3);

	while (!s.empty()) {
		Teacher tmp = s.top();
		tmp.printT();
		s.pop();
	}
}

void main() {
	main52();
}

结果

age: 33
age: 32
age: 31

类指针

//Teacher节点
class Teacher {
public:
	int age;
	char name[32];
	void printT() {
		cout << "age: " << age << endl;
	}
};

void main53() {
	Teacher t1, t2, t3;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;

	stack<Teacher*> s;
	s.push(&t1);
	s.push(&t2);
	s.push(&t3);

	while (!s.empty()) {
		Teacher* p = s.top();
		p->printT();
		s.pop();
	}
}

void main() {
	//main51();
	//main52();
	main53();
}

结果

age: 33
age: 32
age: 31

6 Queue容器

基本数据类型

#include<iostream>
#include<queue>
using namespace std;
// 队列中基本数据类型
// 队列算法和基本数据分离
void main61() {
	queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);

	cout << "队列头元素:" << q.front() << endl;
	cout << "队列尾元素" << q.back() << endl;
	cout << "队列大小" << q.size() << endl;

	while (!q.empty()) {
		cout << q.front() << " ";
		q.pop();
	}
}
void main() {
	main61();
}

结果

队列头元素:1
队列尾元素3
队列大小3
1 2 3

#include<iostream>
#include<queue>
using namespace std;

//Teacher节点
class Teacher {
public:
	int age;
	char name[32];
	void printT() {
		cout << "age: " << age << endl;
	}
};

void main62() {
	Teacher t1, t2, t3;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;
	queue<Teacher> q;
	q.push(t1);
	q.push(t2);
	q.push(t3);

	while (!q.empty()) {
		Teacher tmp = q.front();
		tmp.printT();
		q.pop();
	}
}

void main() {
	main62();
}

结果

age: 31
age: 32
age: 33

类指针

#include<iostream>
#include<queue>
using namespace std;

//Teacher节点
class Teacher {
public:
	int age;
	char name[32];
	void printT() {
		cout << "age: " << age << endl;
	}
};


void main63() {
	Teacher t1, t2, t3;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;
	queue<Teacher*> q;
	q.push(&t1);
	q.push(&t2);
	q.push(&t3);

	while (!q.empty()) {
		Teacher *tmp = q.front();
		tmp->printT();
		q.pop();
	}
}
void main() {
	main63();
}

结果

age: 31
age: 32
age: 33

7 List 容器

list是一个双向链表容器,可以高效地插入和删除元素

list不能随机存取元素,不支持at和[] lt + 5(错误)

插入

#include<iostream>
#include<list>
using namespace std;

void main71() {
	list<int> l;
	cout << "list的大小:" << l.size() << endl;
	for (int i = 0; i < 10; i++) {
		l.push_back(i);	//尾部插入
	}
	cout << "list的大小:" << l.size() << endl;

	list<int>::iterator it = l.begin();

	while (it != l.end()) {
		cout << *it << " ";
		it++;
	}

	cout << endl;
	// list不能随机访问
	it = l.begin();
	it++;
	it++;
	it++;
	//it = it + 5;	不支持随机访问容器
	l.insert(it, 100);

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

	// 结论: 1	链表的节点 index从0开始
	//		  2 在3插入元素是让原来3号位置变成4号位置
}

void main() {
	main71();
}

结果

list的大小:0
list的大小:10
0 1 2 3 4 5 6 7 8 9
0 1 2 100 3 4 5 6 7 8 9

删除

#include<iostream>
#include<list>
using namespace std;

// list 删除
void main72() {
	list<int> l;
	cout << "list的大小:" << l.size() << endl;
	for (int i = 0; i < 10; i++) {
		l.push_back(i);	//尾部插入
	}
	cout << "list的大小:" << l.size() << endl;

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


	list<int>::iterator it1 = l.begin();
	list<int>::iterator it2 = l.begin();
	it2++;
	it2++; 
	it2++;
	l.erase(it1, it2);

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

	l.erase(l.begin());
	l.remove(7);	// 删除list中的某一个数
	for (list<int>::iterator it = l.begin(); it != l.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}

void main() {
	//main71();
	main72();
}

结果

list的大小:0
list的大小:10
0 1 2 3 4 5 6 7 8 9
3 4 5 6 7 8 9
4 5 6 8 9

8 优先级队列 priority_queue

最大值优先级队列,最小值优先级队列

#include<iostream>
#include<queue>
using namespace std;

void main81() {
	priority_queue<int> p1;	//默认 最大值优先级队列
	priority_queue<int, vector<int>, less<int>> p2;	// 提前定义好的预定义函数,上面的默认形式
	priority_queue<int, vector<int>, greater<int>> p3;// 最小值优先级队列

	p1.push(33);
	p1.push(11);
	p1.push(55);
	p1.push(22);

	cout << "队头元素:" << p1.top() << endl;
	cout << "队列大小:" << p1.size() << endl;

	while (!p1.empty()) {
		cout << p1.top() << " ";
		p1.pop();
	}
	cout << endl << endl;
	cout << "最小值优先级队列" << endl;

	p3.push(33);
	p3.push(11);
	p3.push(55);
	p3.push(22);

	cout << "队头元素:" << p3.top() << endl;
	cout << "队列大小:" << p3.size() << endl;

	while (!p3.empty()) {
		cout << p3.top() << " ";
		p3.pop();
	}


}

void main() {
	main81();
}

结果

队头元素:55
队列大小:4
55 33 22 11

最小值优先级队列
队头元素:11
队列大小:4
11 22 33 55

9 set/multiset

1 set

set是一个容器集合,其中包含的元素是唯一的,集合中的元素按一定的顺序排列,元素插入过程是按顺序规则插入,不能指定插入位置

红黑树的变体

不能直接存取元素

#include<iostream>
#include<set>
using namespace std;


// 1 集合 元素唯一 自动排序(默认从小到大) 不能按照[] at方式插入元素
// 红黑树 平衡二叉树
void main91() {
	set<int> set1;
	for (int i = 0; i < 5; i++) {
		int tmp = rand();
		set1.insert(tmp);
	}
	set1.insert(100);
	set1.insert(100);
	set1.insert(100);

	for (set<int>::iterator it = set1.begin(); it != set1.end(); it++) {
		cout << *it << " ";
	}
    // 删除集合
	while (!set1.empty()) {
		set<int>::iterator it = set1.begin();
		cout << *it << " ";	
		set1.erase(set1.begin());
	}
}

void main() {
	main91();
}

结果

41 100 6334 18467 19169 26500
41 100 6334 18467 19169 26500

从大到小

void main92() {
	set<int> set1;
	set<int,less<int>> set2;	// 默认情况
	set<int, greater<int>> set3;	// 从大到小
	for (int i = 0; i < 5; i++) {
		int tmp = rand();
		set3.insert(tmp);
	}
	for (set<int, greater<int>>::iterator it = set3.begin(); it != set3.end(); it++) {
		cout << *it << " ";
	}
}

void main() {
	main92();
}

结果

26500 19169 18467 6334 41

自定义数据类型比较

// 仿函数
struct FuncStudent {
	bool operator()(const Student &left, const Student &right) {
		if (left.age < right.age) {
			return true;	// 从小到大按照年龄进行排序
		}
		else {
			return false;
		}
	}
};
void main93() {
	Student s1("s1", 31);
	Student s2("s2", 22);
	Student s3("s3", 44);
	Student s4("s4", 11);
	Student s5("s5", 31);

	// using _Pairib = pair<iterator, bool>; insert返回值
	set<Student, FuncStudent> set1;
	pair<set<Student, FuncStudent>::iterator, bool> pair1 = set1.insert(s1);
	if (pair1.second == true) {
		cout << "插入s1成功" << endl;
	}
	else {
		cout << "插入s1失败" << endl;
	}
	set1.insert(s2);
	set1.insert(s3);
	set1.insert(s4);
	pair<set<Student, FuncStudent>::iterator, bool> pair5 = set1.insert(s5);	//如果两个31岁,不能插入
	if (pair5.second == true) {
		cout << "插入s5成功" << endl;
	}
	else {
		cout << "插入s5失败" << endl;
	}
	

	// 遍历
	for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++) {
		cout << it->name << ": " << it->age << endl;
	}

	
}

void main() {
	main93();
}

结果

插入s1成功
插入s5失败
s4: 11
s2: 22
s1: 31
s3: 44

find查找,equal_range找大于等于和大于的指针,返回值pair的应用

void main95() {
	set<int> set1;
	for (int i = 0; i < 10; i++) {
		set1.insert(i+1);
	}
	for (set<int, greater<int>>::iterator it = set1.begin(); it != set1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;

	set<int>::iterator it0 = set1.find(5);
	cout << "it0:" << *it0 << endl;

	int num1 = set1.count(5);
	cout << "num1: " << num1 << endl;

	set<int>::iterator it1 = set1.lower_bound(5); // 大于等于5元素迭代器位置
	cout << "it1:" << *it1 << endl;

	set<int>::iterator it2 = set1.upper_bound(5); // 大于5元素迭代器位置
	cout << "it2:" << *it2 << endl;

	//using _Pairii = pair<iterator, iterator>; 返回值

	// 删除元素5
	set1.erase(5);
	pair<set<int>::iterator, set<int>::iterator> mypair = set1.equal_range(5);
	set<int>::iterator it3 = mypair.first; 
	cout << "it3:" << *it3 << endl;	// 6
	set<int>::iterator it4 = mypair.second;
	cout << "it4:" << *it4 << endl;	// 6
}

void main() {
	main95();
}

结果

1 2 3 4 5 6 7 8 9 10
it0:5
num1: 1
it1:5
it2:6
it3:6
it4:6

2 multiset

multiset同一个值可以出现多个

// multiset
void main1001() {
	multiset<int> set1;
	int tmp = 0;
	printf("请输入multiset集合值:");
	scanf("%d", &tmp);
	while(tmp != 0) {
		set1.insert(tmp);
		printf("请输入multiset集合值:");
		scanf("%d", &tmp);
	}

	// 遍历
	for (multiset<int>::iterator it = set1.begin(); it != set1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;

	while (!set1.empty()) {
		multiset<int>::iterator it = set1.begin();
		cout << *it << " ";
		set1.erase(set1.begin());
	}

}
void main() {
	main1001();
}

结果

请输入multiset集合值:2
请输入multiset集合值:3
请输入multiset集合值:4
请输入multiset集合值:20
请输入multiset集合值:2
请输入multiset集合值:4
请输入multiset集合值:3
请输入multiset集合值:0
2 2 3 3 4 4 20
2 2 3 3 4 4 20

10 map/multimap

1 map

  • map中的key值唯一,集合中的元素按照一定顺序排列,即(key, value),插入按排列顺序插入不能指定插入位置

  • map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。

  • map可以直接获取key的value 支持[] 即 map[key] = value

  • multimap相同key可以出现多次,不支持[]

map元素添加/遍历/删除

#include<iostream>
#include<map>
#include<string>
using namespace std;

// map元素添加/遍历/删除
void main1101() {
	map<int, string> map1;

	// 方法1
	map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	// 方法2 
	map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	// 方法3
	map1.insert(map<int, string>::value_type(5, "teacher05"));
	map1.insert(map<int, string>::value_type(6, "teacher06"));

	// 方法4
	map1[7] = "teacher07";
	map1[8] = "teacher08";

	// 容器遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++) {
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;

	// 容器删除
	while (!map1.empty()) {
		map<int, string>::iterator it = map1.begin();
		cout << it->first << "\t" << it->second << endl;
		map1.erase(it);
	}
}

void main() {
	main1101();
}

结果

1       teacher01
2       teacher02
3       teacher03
4       teacher04
5       teacher05
6       teacher06
7       teacher07
8       teacher08
遍历结束
1       teacher01
2       teacher02
3       teacher03
4       teacher04
5       teacher05
6       teacher06
7       teacher07
8       teacher08


插入四种方法的异同

// 插入四种方法的异同
// 前三种返回值是pair<iterator, bool> 若key存在则报错
// 方法四若key存在则覆盖
void main1102() {
	map<int, string> map1;

	//using _Pairib = pair<iterator, bool>;

	// 方法1
	pair<map<int,string>::iterator,bool> mypair1 = map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	// 方法2 
	pair<map<int, string>::iterator, bool> mypair3 = map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	// 方法3
	pair<map<int, string>::iterator, bool> mypair5 = map1.insert(map<int, string>::value_type(5, "teacher05"));
	if (mypair5.second == true) {
		cout << "key 5 插入成功" << endl;
		cout << mypair5.first->first << "\t" << mypair5.first->second << endl;
	}
	else {
		cout << "key 5 插入失败" << endl;
	}
	pair<map<int, string>::iterator, bool> mypair6 = map1.insert(map<int, string>::value_type(5, "teacher55"));
	if (mypair6.second == true) {
		cout << "key 6 插入成功" << endl;
		cout << mypair6.first->first << "\t" << mypair6.first->second << endl;
	}
	else {
		cout << "key 6 插入失败" << endl;
	}

	// 方法4
	map1[7] = "teacher07";
	map1[7] = "teacher77"; 
	// 容器遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++) {
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;
}

void main() {
	main1102();
}

结果

key 5 插入成功
5       teacher05
key 6 插入失败
1       teacher01
2       teacher02
3       teacher03
4       teacher04
5       teacher05
7       teacher77
遍历结束

find lower_bound >= upper_bound > equal_range() > >=

void main1103() {
	map<int, string> map1;

	// 方法1
	map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	// 方法2 
	map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	// 方法3
	map1.insert(map<int, string>::value_type(5, "teacher05"));
	map1.insert(map<int, string>::value_type(6, "teacher06"));

	// 方法4
	map1[7] = "teacher07";
	map1[8] = "teacher08";

	// 容器遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++) {
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;

	// map查找	异常处理
	map<int, string>::iterator it2 = map1.find(100);
	if (it2 == map1.end()) {
		cout << "key 100的值不存在" << endl;
	}
	else {
		cout << it2->first << "\t" << it2->second << endl;
	}

	// equal_range
	pair<map<int, string>::iterator, map<int, string>::iterator>mypair = map1.equal_range(5);	//返回两个迭代器,形成一对pair
	// 第一个迭代器 >=5 的位置 第二个迭代器>5的位置
	if (mypair.first == map1.end()) {
		cout << "第一个迭代器 >=5 的位置不存在" << endl;
	}
	else {
		cout << mypair.first->first << "\t" << mypair.first->second << endl;
	}

	if (mypair.second == map1.end()) {
		cout << "第二个迭代器 >5 的位置不存在" << endl;
	}
	else {
		cout << mypair.second->first << "\t" << mypair.second->second << endl;
	}
}

void main() {
	main1103();
}

结果

1       teacher01
2       teacher02
3       teacher03
4       teacher04
5       teacher05
6       teacher06
7       teacher07
8       teacher08
遍历结束
key 100的值不存在
5       teacher05
6       teacher06

2 multimap

员工案例

#include<iostream>
#include<map>
#include<string>
using namespace std;


// Multimap 案例 :
//1个key值可以对应多个valude  =分组 
//公司有销售部 sale (员工2名)、技术研发部 development (1人)、财务部 Financial (2人) 
//人员信息有:姓名,年龄,电话、工资等组成
//通过 multimap进行 信息的插入、保存、显示
//分部门显示员工信息 

class Person {
public:
	string	name;
	int		age;
	string	tel;
	double	sal;
};

void main1201() {
	Person p1, p2, p3, p4, p5;
	
	p1.name = "s1";
	p1.age = 31;

	p2.name = "s2";
	p2.age = 32;
	
	p3.name = "t3";
	p3.age = 33;
	
	p4.name = "f4";
	p4.age = 34;
	
	p5.name = "f5";
	p5.age = 35;

	multimap<string, Person> map2;
	// sale 部门
	map2.insert(make_pair("sale", p1));
	map2.insert(make_pair("sale", p2));
	//development
	map2.insert(make_pair("development", p3));
	
	// Financial
	map2.insert(make_pair("financial", p4));
	map2.insert(make_pair("financial", p5));

	for (multimap<string, Person>::iterator it = map2.begin(); it != map2.end(); it++) {
		cout << it->first << "\t" << it->second.name << endl;
	}
	cout << "输出完成" << endl;

	// 按部门显示
	int num2 = map2.count("development");
	cout << "开发部人数:" << num2 << endl << endl;
	cout << "部门员工信息:" << endl;
	multimap<string, Person>::iterator it2 = map2.find("development");
	int tag = 0;
	/*while (it2 != map2.end() && tag < num2) {
		cout << it2->first << "\t" << it2->second.name << endl;
		it2++;
		tag++;
	}*/
	while (tag < num2) {
		cout << it2->first << "\t" << it2->second.name << endl;
		it2++;
		tag++;
	}
}

void main() {
	main1201();
}

结果

development     t3
financial       f4
financial       f5
sale    s1
sale    s2
输出完成
开发部人数:1

部门员工信息:
development     t3

//age =32修改为name32
void main1202() {
	Person p1, p2, p3, p4, p5;

	p1.name = "s1";
	p1.age = 31;

	p2.name = "s2";
	p2.age = 32;

	p3.name = "t3";
	p3.age = 33;

	p4.name = "f4";
	p4.age = 34;

	p5.name = "f5";
	p5.age = 35;

	multimap<string, Person> map2;
	// sale 部门
	map2.insert(make_pair("sale", p1));
	map2.insert(make_pair("sale", p2));
	//development
	map2.insert(make_pair("development", p3));

	// Financial
	map2.insert(make_pair("financial", p4));
	map2.insert(make_pair("financial", p5));

	cout << "按条件检索并修改" << endl;
	for (multimap<string, Person>::iterator it = map2.begin(); it != map2.end(); it++) {
		//cout << it->first << "\t" << it->second.name << endl;
		if (it->second.age == 32) {
			it->second.name = "name32";
		}
	}
	
	for (multimap<string, Person>::iterator it = map2.begin(); it != map2.end(); it++) {
		cout << it->first << "\t" << it->second.name << endl;
	}
	cout << "输出完成" << endl;
}

void main() {
	main1202();
}

结果

按条件检索并修改
development     t3
financial       f4
financial       f5
sale    s1
sale    name32
输出完成

11 容器共性

所有容器提供的都是值(value)语意,而非引用(reference)语意

容器执行插入元素操作时,内部实施拷贝动作。STL容器内存储的元素必须能被拷贝(必须提供拷贝构造函数)

重载=运算符

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>

using namespace std;

class Teacher {

public:
	Teacher(char* name, int age) {
		m_pname = new char[strlen(name) + 1];
		strcpy(m_pname, name);
		m_age = age;
	}
	Teacher(const Teacher& obj) {
		m_pname = new char[strlen(obj.m_pname) + 1];
		strcpy(m_pname, obj.m_pname);
		m_age = obj.m_age;
	}
	~Teacher() {
		if (m_pname != NULL) {
			delete[]m_pname;
			m_pname = NULL;
			m_age = 0;
		}
	}

	//重载= 操作符
	Teacher& operator=(const Teacher& t1) {
		if (m_pname != NULL) {
			delete[]m_pname;
			m_pname = NULL;
			m_age = 0;
		}
		m_pname = new char[strlen(t1.m_pname) + 1];
		strcpy(m_pname, t1.m_pname);
		m_age = t1.m_age;
		return *this;
	}

	void printT() {
		cout << m_pname << "\t" << m_age << endl;
	}
private:
	char* m_pname;
	int		m_age;
};

void main1301() {
	Teacher t1((char*)"t1", 31);
	t1.printT();
	vector<Teacher> v1;
	v1.push_back(t1);	//把t1拷贝了一份存入容器中
}

void main() {
	main1301();
}

12 算法

1 函数对象

重载函数调用操作符的类,其对象常称为函数对象(function object)

#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>

using namespace std;


//函数对象:类重载了操作符
template<typename T>
class ShowElement{
public:
	void operator()(T& t) {
		cout << t << " ";
	}
};

// 函数模板
template<typename T>
void FuncShowElement(T &t) {
	cout << t << endl;
}

//普通函数
void FuncShowElement2(int& t) {
	cout << t << endl;
}

// 函数对象定义
void main01() {
	int a = 10;
	ShowElement<int> showElement;
	showElement(a);	//函数对象的()执行 很像一个函数 仿函数

	FuncShowElement<int>(a);
	FuncShowElement2(a);
}


void main() {
	main01();
}

函数对象好处,可以记录调用函数对象的次数?(不太理解这个用处)

#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>

using namespace std;


//函数对象:类重载了操作符
template<typename T>
class ShowElement{
public:
	ShowElement() {
		n = 0;
	}
	void operator()(T& t) {
		n++;
		// printN();
		cout << t << " ";
	}
	void printN() {
		cout << "n:" << n << endl;
	}
private:
	int n;
};

// 函数模板
template<typename T>
void FuncShowElement(T &t) {
	cout << t << endl;
}

//普通函数
void FuncShowElement2(int& t) {
	cout << t << endl;
}


// 函数对象属于类对象,能保持调用状态信息
// 函数对象的好处 
// for_each算法中函数对象做函数参数
// for_each算法中函数对象当返回值
void main02() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	for_each(v1.begin(), v1.end(), ShowElement<int>());	//匿名函数对象,匿名仿函数
	cout << endl;
	for_each(v1.begin(), v1.end(), FuncShowElement2);	//通过回调函数	使用for_each,需要填写回调函数的入口地址

	ShowElement<int> show1;
	// 函数对象做函数参数
	// for_each函数是元素值的传递不是引用传递
	for_each(v1.begin(), v1.end(), show1);
	show1.printN();

	cout << "通过for_each算法的返回值观察调用次数" << endl;
	show1 = for_each(v1.begin(), v1.end(), show1);
	show1.printN();
}
void main() {
	main02();
}

结果

1 3 5
1
3
5
1 3 5 n:0
通过for_each算法的返回值观察调用次数
1 3 5 n:3

2 函数对象和谓词

一元函数对象:函数参数1个;

二元函数对象:函数参数2个;

一元谓词 函数参数1个,函数返回值是bool类型,可以作为一个判断式

​ 谓词可以使一个仿函数,也可以是一个回调函数。

二元谓词 函数参数2个,函数返回值是bool类型

一元函数 谓词

#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>

template<typename T>
class IsDiv {
public:
	IsDiv(const T& divisor) {
		this->divisor = divisor;
	}
	bool operator()(T& t) {
		return (t % divisor == 0);
	}
private:
	T divisor;
};

void main03() {
	vector<int> v2;
	for (int i = 10; i < 33; i++) {
		v2.push_back(i);
	}
	int a = 4;
	IsDiv<int> myDiv(a);

	//find_if(v2.begin(), v2.end(), myDiv);
	vector<int>::iterator it;

	/*
	// FUNCTION TEMPLATE find_if
	template <class _InIt, class _Pr>
	_NODISCARD inline _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) { // find first satisfying _Pred
		_Adl_verify_range(_First, _Last);
		auto _UFirst = _Get_unwrapped(_First);
		const auto _ULast = _Get_unwrapped(_Last);
		for (; _UFirst != _ULast; ++_UFirst) {
			if (_Pred(*_UFirst)) {
				break;
			}
		}

		_Seek_wrapped(_First, _UFirst);
		return _First;
	}

	find_if 返回迭代器
	*/
	


	it = find_if(v2.begin(), v2.end(), IsDiv<int>(4));
	if (it == v2.end()) {
		cout << "容器中没有值为4倍数的元素" << endl;
	}
	else {
		cout << "第一个被4整除元素:" << *it << endl;
	}
}
void main() {
	//main01();
	//main02();
	main03(); // 一元谓词
}

结果

第一个被4整除元素:12

二元函数

void main04() {
	// v1 v2 ===> v3
	vector<int> v1, v2;
	vector<int> v3;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	v3.resize(10);
	
	/*
	template <class _InIt1, class _InIt2, class _OutIt, class _Fn>
inline _OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest,
    _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...) with _Func
    _Adl_verify_range(_First1, _Last1);
    auto _UFirst1      = _Get_unwrapped(_First1);
    const auto _ULast1 = _Get_unwrapped(_Last1);
    const auto _Count  = _Idl_distance<_InIt1>(_UFirst1, _ULast1);
    auto _UFirst2      = _Get_unwrapped_n(_First2, _Count);
    auto _UDest        = _Get_unwrapped_n(_Dest, _Count);
    for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2, ++_UDest) {
        *_UDest = _Func(*_UFirst1, *_UFirst2);
    }

    _Seek_wrapped(_Dest, _UDest);
    return _Dest;
}
	// transform 返回运算结果开始位置的迭代器
	*/
	transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>());

	for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++) {
		cout << *it << " ";
	}
}
void main() {
	main04();	// 二元函数对象
}

结果

3 7 11 0 0 0 0 0 0 0

二元谓词

bool MyCompare(const int& a, const int& b) {
	return a < b;	// 从小到大
}
//二元谓词
void main05(){
	vector<int> v1(10);
	for (int i = 0; i < 10; i++) {
		int tmp = rand() % 100;
		v1[i] = tmp;
	}
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;

	for_each(v1.begin(), v1.end(), FuncShowElement2);
	cout << endl;

	sort(v1.begin(), v1.end(), MyCompare);
	for_each(v1.begin(), v1.end(), FuncShowElement2);
	cout << endl;
}
void main() {
	main05();
}

结果

41 67 34 0 69 24 78 58 62 64
41 67 34 0 69 24 78 58 62 64
0 24 34 41 58 62 64 67 69 78

集合二元谓词

struct CompareNoCase {
	bool operator()(const string &str1, const string &str2) const {	// 需要加入const 防止丢失const属性
		string str1_;
		str1_.resize(str1.size());
		transform(str1.begin(), str1.end(), str1_.begin(), tolower);//预定义函数对象

		string str2_;
		str2_.resize(str2.size());
		transform(str2.begin(), str2.end(), str2_.begin(), tolower);//预定义函数对象

		return (str1_ < str2_);	//从小到大排序
	}
};
void main06() {
	set<string> set1;
	set1.insert("bbb");
	set1.insert("aaa");
	set1.insert("ccc");
	set<string>::iterator it = set1.find("aAa");//find函数默认区分大小写
	if (it == set1.end()) {
		cout << "未查找到aaa" << endl;
	}
	else {
		cout << "查找到aaa" << endl;
	}

	set<string, CompareNoCase> set2;
	set2.insert("bbb");
	set2.insert("aaa");
	set2.insert("ccc");

	set<string, CompareNoCase>::iterator it2 = set2.find("aAa");
	if (it2 == set2.end()) {
		cout << "未查找到aaa" << endl;
	}
	else {
		cout << "(不区分大小写)查找到aaa" << endl;
	}
}

void main() {
	main06();	//二元谓词在set集合中的应用
}

结果

未查找到aaa
(不区分大小写)查找到aaa

3 预定义函数对象和函数适配器

#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>
#include<set>

using namespace std;

// plus<int> 预定义好的函数对象 能实现不同类型的数据 + 运算
// 实现了 数据类型和算法的分离===>>通过函数对象技术实现

// plus<type>是两个参数?
void main21() {
	plus<int> intAdd;
	int x = 10;
	int y = 20;
	int z = intAdd(x, y);	// x+y
	cout << "z:" << z << endl;

	plus<string> stringAdd;
	string s1 = "aaa";
	string s2 = "bbb";
	string s3 = stringAdd(s1, s2);
	cout << "s3: " << s3 << endl;

	vector<string> v1;
	v1.push_back("bbb");
	v1.push_back("aaa");
	v1.push_back("ccc");
	v1.push_back("zzz");
	v1.push_back("ccc");
	v1.push_back("ccc");

	sort(v1.begin(), v1.end(), greater<string>());

	for (vector<string>::iterator it = v1.begin(); it != v1.end(); it++) {
		cout << *it << " ";
	}
	// 求ccc个数
	string sc = "ccc";
	// bind2nd 有两个参数 left 来自容器,right来自sc
	// equal_to<string>() 函数适配器 把预定义函数对象和第二个参数进行绑定
	int num = count_if(v1.begin(), v1.end(), bind2nd(equal_to<string>(),sc));
	cout << "num:" << num << endl;
}
void main() {
	main21();
}

结果

z:30
s3: aaabbb
zzz ccc ccc ccc bbb aaa num:3

常用函数适配器

1绑定器(binder): binder通过把二元函数对象的一个实参绑定到一个特殊的值上,将其转换成一元函数对象。C++标准库提供两种预定义的binder适配器:bind1st和bind2nd,前者把值绑定到二元函数对象的第一个实参上,后者绑定在第二个实参上。

2取反器(negator) : negator是一个将函数对象的值翻转的函数适配器。标准库提供两个预定义的ngeator适配器:not1翻转一元预定义函数对象的真值,而not2翻转二元谓词函数的真值。

常用函数适配器列表如下:

bind1st(op, value)

bind2nd(op, value)

not1(op)

not2(op)

class IsGreat
{
public:
	IsGreat(int i) {
		m_num = i;
	}
	bool operator()(const int& num) {
		return m_num < num;
	}
private:
	int m_num;
};

void main22() {
	vector<int> v1;
	for (int i = 0; i < 10; i++) {
		v1.push_back(i + 1);
	}
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
	int num1 = count(v1.begin(), v1.end(), 3);
	cout << "num1:" << num1 << endl;

	// 通过谓词求大于2的个数
	int num2 = count_if(v1.begin(), v1.end(), IsGreat(2));
	cout << "num2:" << num2 << endl;



	/*
	// STRUCT TEMPLATE greater
	template <class _Ty = void>
	struct greater { // functor for operator>
		_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
		_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
		_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef bool result_type;

		constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const { // apply operator> to operands
			return _Left > _Right;
		}
	};
	*/
	// 通过预定义函数对象 求大于2的个数
	// greater<int>()有两个参数 左参数来自容器的元素,右参数固定成2(通过bind2nd())
	int num3 = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(),2));
	cout << "num3:" << num3 << endl;

	// 求奇数的个数
	int num4 = count_if(v1.begin(), v1.end(), bind2nd(modulus<int>(), 2));
	cout << "num4:" << num4 << endl;

	// 求偶数的个数
	int num5 = count_if(v1.begin(), v1.end(), not1(bind2nd(modulus<int>(), 2)));
	cout << "num5:" << num5 << endl;
}

void main() {
	//main21();
	main22();	// 适配器综合案例
}

结果

1 2 3 4 5 6 7 8 9 10
num1:1
num2:8
num3:8
num4:5
num5:5

13 常用遍历算法

for_each 用指定函数依次对指定范围内所有元素进行迭代访问。该函数不得修改序列中的元素。

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>
#include<set>


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


void showElement(int& n) {
	cout << n << " ";
}

class CMyShow {
public:
	CMyShow() {
		num = 0;
	}
	void operator()(int& n) {
		num++;
		cout << n << " ";
	}
	void printNum() {
		cout << "num:" << num << endl;
	}
private:
	int num;
};

void main41_foreach() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	printV(v1);

	// for_each : 用指定函数依次对指定范围内所有元素进行迭代访问。该函数不得修改序列中的元素。
	// 第三个位置是函数对象或者回调函数入口地址
	for_each(v1.begin(), v1.end(), showElement);
	cout << endl;
	for_each(v1.begin(), v1.end(), CMyShow());
	cout << endl;

	CMyShow mya;
	/*CMyShow my1 = for_each(v1.begin(), v1.end(), CMyShow());
	my1.printNum();*/
	CMyShow my1 = for_each(v1.begin(), v1.end(), mya);	// my1初始化
	mya.printNum();// mya 和 my1是两个不同的对象
	my1.printNum();//my1赋值
}
void main() {
	main41_foreach();
}

结果

1 3 5
1 3 5
1 3 5
1 3 5 num:0
num:3

transform: 与for_each类似,遍历所有元素,但可对容器的元素进行修改 两个容器变为一个容器

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>
#include<set>
#include<iterator>


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

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

int increase(int i) {
	return i + 100;
}

void main42_transform() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	printV(v1);

	//使用回调函数
	transform(v1.begin(), v1.end(), v1.begin(), increase);	
	printV(v1);

	// 使用预定义函数对象
	transform(v1.begin(), v1.end(), v1.begin(), negate<int>());
	printV(v1);

	// 使用函数适配器 和 函数对象
	list<int> mylist;
	mylist.resize(v1.size());
	transform(v1.begin(), v1.end(), mylist.begin(), bind2nd(multiplies<int>(),10));
	printL(mylist);

	// transform直接把结果输出到屏幕
	transform(v1.begin(), v1.end(), ostream_iterator<int>(cout," "),negate<int>());
}

void main() {
	main42_transform();
}
1 3 5
101 103 105
-101 -103 -105
-1010 -1030 -1050
101 103 105

案例

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include<functional>
#include<set>
#include<iterator>

void showElement(int& n) {
	cout << n << " ";
}

int showElement2(int& n) {
	cout << n << " ";
	return n;
}

void main43_transform_pk_foreach() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	vector<int>v2 = v1;
	
	for_each(v1.begin(), v1.end(), showElement);
	cout << endl;

	//transform回调函数要求返回值

	/*
	// FUNCTION TEMPLATE transform
	template <class _InIt, class _OutIt, class _Fn>
	inline _OutIt transform(
		const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func) { // transform [_First, _Last) with _Func
		_Adl_verify_range(_First, _Last);
		auto _UFirst      = _Get_unwrapped(_First);
		const auto _ULast = _Get_unwrapped(_Last);
		auto _UDest       = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
		for (; _UFirst != _ULast; ++_UFirst, (void) ++_UDest) {
			*_UDest = _Func(*_UFirst);	// 解释了要有返回值的原因
		}

		_Seek_wrapped(_Dest, _UDest);
		return _Dest;
	}
	*/
	transform(v2.begin(), v2.end(), v2.begin(),	showElement2);
	cout << endl;
}

void main() {
	main43_transform_pk_foreach();
}

结果

1 3 5
1 3 5

for_each使用函数对象参数是引用,没有返回值

transform参数一般不使用引用,有返回值

14 常见查找算法

1 adjacent_find()

在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的迭代器。否则返回past-the-end。

void main44_adjacent_find() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(5);

	vector<int>::iterator it = adjacent_find(v1.begin(), v1.end());
	if (it == v1.end()) {
		cout << "没有找到 重复元素" << endl;
	}
	else {
		cout << *it << endl;
	}

	int index = distance(v1.begin(), it);
	cout << index << endl;

}

void main() {
	main44_adjacent_find();
}

结果

2
1

2 binary_search

在有序序列中查找value,找到则返回true。注意:在无序序列中,不可使用。

void main45_binary_search() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(9);

	bool b = binary_search(v1.begin(), v1.end(), 7);
	if (b) {
		cout << "找到" << endl;
	}
	else {
		cout << "未找到" << endl;
	}
}
void main() {
	main45_binary_search();
}

3 count()

利用等于操作符,把标志范围内的元素与输入值比较,返回相等的个数。

void main46_count() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(7);
	v1.push_back(9);
	v1.push_back(7);

	int num = count(v1.begin(), v1.end(), 7);
	cout << num << endl;
}
void main() {
	main46_count();
}

4 count_if

bool GreaterThree(int iNum) {
	if (iNum > 3) {
		return true;
	}
	else {
		return false;
	}
}
void main47_count_if() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(7);
	v1.push_back(9);
	v1.push_back(7);

	int num = count_if(v1.begin(), v1.end(), GreaterThree);
	cout << num << endl;
}
void main() {
	main47_count_if();
}

5 find find_if

bool GreaterThree(int iNum) {
	if (iNum > 3) {
		return true;
	}
	else {
		return false;
	}
}
void main48_find_findif() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(7);
	v1.push_back(9);
	v1.push_back(7);

	vector<int>::iterator it = find(v1.begin(), v1.end(), 7);
	cout << *it << endl;

	vector<int>::iterator it2 = find_if(v1.begin(), v1.end(), GreaterThree);
	cout << *it2 << endl;
}
void main() {
	main48_find_findif();
}

15 常用排序算法

1 merge

合并两个有序序列,存放到另一个序列

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_merge() {
	vector<int> v1, v2;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	vector<int> v3;
	v3.resize(v1.size() + v2.size());
	printV(v3);

	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	printV(v3);

}
void main() {
	main_merge();
}

2 sort

以默认升序的方式重新排列指定范围内的元素。若要改排序规则,可以输入比较函数。

class Student {
public:
	Student(string name, int id) {
		m_name = name;
		m_id = id;
	}
	void printS() {
		cout << "name:" << m_name << "\t" << "id:" << m_id << endl;
	}
public:
	string m_name;
	int	m_id;
};

bool CompareS(Student& s1, Student& s2) {
	return (s1.m_id < s2.m_id);
}

void main_sort() {
	Student s1("first", 1);
	Student s2("second", 2);
	Student s3("third", 3);
	Student s4("forth", 4);
	vector<Student> v1;
	v1.push_back(s4);
	v1.push_back(s2);
	v1.push_back(s3);
	v1.push_back(s1);

	for (vector<Student>::iterator it = v1.begin(); it != v1.end(); it++) {
		it->printS();
	}
	// sort根据自定义函数对象排序 算法和数据类型的分离
	sort(v1.begin(), v1.end(), CompareS);
	for (vector<Student>::iterator it = v1.begin(); it != v1.end(); it++) {
		it->printS();
	}

}
void main() {
	main_sort();
}

结果

name:forth      id:4
name:second     id:2
name:third      id:3
name:first      id:1
name:first      id:1
name:second     id:2
name:third      id:3
name:forth      id:4

3 random_shuffle()

对指定范围内的元素随机调整次序。

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_random_shuffle() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	random_shuffle(v1.begin(), v1.end());
	printV(v1);

	string str = "abcdefg";
	random_shuffle(str.begin(), str.end());
	cout << "str:" << str << endl;
}
void main() {
	main_random_shuffle();
}

结果

1 3 7 5
str:facebgd

4 reverse

倒序

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_reverse() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	printV(v1);
	reverse(v1.begin(), v1.end());
	printV(v1);
}
void main() {
	main_reverse();
}

结果

1 3 5 7
7 5 3 1

16 拷贝和替换算法

1 copy

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_copy() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);

	vector<int> v2;
	v2.resize(v1.size());
	copy(v1.begin(), v1.end(), v2.begin());
	printV(v2);
}
void main() {
	main_copy();
}

2 replace/replace_if

replace(beg,end,oldValue,newValue): 将指定范围内的所有等于oldValue的元素替换成newValue。

replace_if : 将指定范围内所有操作结果为true的元素用新值替换。

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
bool greater_equal_5(int& n) {
	return n >= 5;
}
void main_replace_replaceif() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(3);

	printV(v1);
	replace(v1.begin(), v1.end(), 3, 8);
	printV(v1);

	replace_if(v1.begin(), v1.end(), greater_equal_5, 1);
	printV(v1);

}
void main() {
	main_replace_replaceif();
}

结果

1 3 5 7 3
1 8 5 7 8
1 1 1 1 1

3 swap

swap: 交换两个容器的元素

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_swap() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	vector<int> v2;
	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	swap(v1, v2);
	printV(v1);
}
void main() {
	main_swap();
}

17 常用算术和生成算法

1 accumulate

accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。

#include<numeric>

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

void main_accumulate() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	int tmp = accumulate(v1.begin(), v1.end(), 100);
	cout << tmp << endl;
}

void main() {
	main_accumulate();
}

2 fill

fill: 将输入值赋给标志范围内的所有元素。

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

void main_fill() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	fill(v1.begin(), v1.end(), 8);
	printV(v1);
}
void main() {
	main_fill();
}

结果

8 8 8

18 常用集合算法

set_union: 构造一个有序序列,包含两个有序序列的并集。

set_intersection: 构造一个有序序列,包含两个有序序列的交集。

set_difference: 构造一个有序序列,该序列保留第一个有序序列中存在而第二个有序序列中不存在的元素。

(需要保证有序)

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_union() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	
	vector<int> v2;
	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	vector<int> v3;
	v3.resize(10);
	set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());	// 并集
	printV(v3);

	fill(v3.begin(), v3.end(), 0);
	set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());//交集
	printV(v3);

	fill(v3.begin(), v3.end(), 0);
	set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());//差集
	printV(v3);
}
void main() {
	main_union();
}

v2;
v2.resize(v1.size());
copy(v1.begin(), v1.end(), v2.begin());
printV(v2);
}
void main() {
main_copy();
}


## 2 replace/replace_if

replace(beg,end,oldValue,newValue):  将指定范围内的所有等于oldValue的元素替换成newValue。

replace_if : 将指定范围内所有操作结果为true的元素用新值替换。

```cpp
void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
bool greater_equal_5(int& n) {
	return n >= 5;
}
void main_replace_replaceif() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v1.push_back(7);
	v1.push_back(3);

	printV(v1);
	replace(v1.begin(), v1.end(), 3, 8);
	printV(v1);

	replace_if(v1.begin(), v1.end(), greater_equal_5, 1);
	printV(v1);

}
void main() {
	main_replace_replaceif();
}

结果

1 3 5 7 3
1 8 5 7 8
1 1 1 1 1

3 swap

swap: 交换两个容器的元素

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_swap() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	vector<int> v2;
	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	swap(v1, v2);
	printV(v1);
}
void main() {
	main_swap();
}

17 常用算术和生成算法

1 accumulate

accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值。

#include<numeric>

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

void main_accumulate() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	int tmp = accumulate(v1.begin(), v1.end(), 100);
	cout << tmp << endl;
}

void main() {
	main_accumulate();
}

2 fill

fill: 将输入值赋给标志范围内的所有元素。

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

void main_fill() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);

	fill(v1.begin(), v1.end(), 8);
	printV(v1);
}
void main() {
	main_fill();
}

结果

8 8 8

18 常用集合算法

set_union: 构造一个有序序列,包含两个有序序列的并集。

set_intersection: 构造一个有序序列,包含两个有序序列的交集。

set_difference: 构造一个有序序列,该序列保留第一个有序序列中存在而第二个有序序列中不存在的元素。

(需要保证有序)

void printV(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
void main_union() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	
	vector<int> v2;
	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	vector<int> v3;
	v3.resize(10);
	set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());	// 并集
	printV(v3);

	fill(v3.begin(), v3.end(), 0);
	set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());//交集
	printV(v3);

	fill(v3.begin(), v3.end(), 0);
	set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());//差集
	printV(v3);
}
void main() {
	main_union();
}

结果

1 2 3 4 5 6 0 0 0 0
4 0 0 0 0 0 0 0 0 0
1 3 5 0 0 0 0 0 0 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值