C++学习三部曲(提高编程)

模板

模板就是建立通用的模具,大大提高复用性

模板类型

函数模板、类模板

函数模板

作用:建立一个通用函数,函数返回类型形参类型可以不具体指定,用一个虚拟的类型表示
语法:template<typename T>,下面写函数声明或者定义

#include<iostream>
using namespace std;

交换两个整型数据
//void swap_int(int& a, int& b)
//{
//	int temp = a;
//	a = b;
//	b = temp;
//}
//
交换两个浮点型数据
//void swap_double(double& a, double& b)
//{
//	double temp = a;
//	a = b;
//	b = temp;
//}

//函数模板
//比如对于上面的函数,实现的功能基本一致,因此可以使用模板的方式
template<typename T> //声明模板
void myswap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

void test01()
{
	int a = 10;
	int b = 20;

	//1 自动类型推导
	//myswap(a, b);

	//2 显示指定类型
	myswap<int>(a, b);

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

}

int main()
{
	test01();
}

a = 20
b = 10

函数模板注意事项

1 模板能够推导出一致的T类型,当然也可以采用诸如template<class T1, class T2>的写法
2 模板必须确定T的数据类型, 才可以使用

#include<iostream>
using namespace std;

template<class T>
void myswap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

//2 模板必须确定T的数据类型, 才可以使用
template<class T>
void func()
{
	cout << "func 调用" << endl;
}

void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';

	myswap(a, b); //正确
	//myswap(a, c); //错误, 推导不出一致的T类型

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}

void test02()
{
	func<int>(); //正确
	//func();  //错误
}

int main()
{
	test01();

	test02();

}

a = 20
b = 10
func 调用

案例——数组排序

#include<iostream>
using namespace std;


//排序算法模板
template<class T>
void mySort(T *arr, int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				T temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

//打印数组模板
template<class T>
void printInfo(T* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}

//测试字符数组
void test01()
{
	char cArr[] = "badcfe";
	int len = sizeof(cArr) / sizeof(cArr[0]);

	mySort<char>(cArr, len);

	printInfo(cArr, len);
}

//测试整型数组
void test02()
{
	int iArr[] = {1, 3, 9, 8, 5, 4, 7};
	int len = sizeof(iArr) / sizeof(iArr[0]);

	mySort<int>(iArr, len);

	printInfo(iArr, len);
}


int main()
{
	test01();

	test02();
}

f e d c b a
9 8 7 5 4 3 1

普通函数和函数模板的区别

普通函数:可发生隐式类型转换(如char与int类型的相加
函数模板:自动类型推导不可,显示指定类型可以发生隐式类型转换

#include<iostream>
using namespace std;

//普通函数
int myAdd01(int a, int b)
{
	return a + b;
}

//模板函数
template<class T>
T myAdd02(T a, T b)
{
	return a + b;
}

void test01()
{
	int a = 10;
	char b = 'a';

	//字符和数字相加,普通函数自动进行隐式类型转换,'a'=97
	int c = myAdd01(a, b);

	cout << "普通函数: " << c << endl;
}

void test02()
{
	int a = 10;
	char b = 'a';

	//1 自动类型推导,无法自动进行隐式类型转换
	//int c = myAdd02(a, b);

	//2 显示指定类型
	int c = myAdd02<int>(a, b);

	cout << "模板函数: " << c << endl;
}

int main()
{
	test01();

	test02();
}

普通函数: 107
模板函数: 107

普通函数和函数模板的调用规则

  1. 若普通函数和函数模板都可以实现,优先调用普通函数
  2. 可以通过空模板参数列表来优先调用函数模板
  3. 函数模板可以发生重载
  4. 若函数模板可实现更好的匹配,则优先调用函数模板
#include<iostream>
using namespace std;

void myPrint(int a, int b)
{
	cout << "调用普通函数" << endl;
}

template<class T>
void myPrint(T a, T b)
{
	cout << "调用函数模板" << endl;
}

//函数模板的重载
template<class T>
void myPrint(T a, T b, T c)
{
	cout << "调用重载的函数模板" << endl;
}

void test01()
{
	int a = 10;
	int b = 20;
	int c = 30;

	myPrint(a, b);  //1 若普通函数和函数模板都可以实现,优先调用普通函数

	myPrint<>(a, b);  //2 可以通过空模板参数列表来优先调用函数模板

	myPrint(a, b, c);  //3 函数模板可以发生重载

	char d = 'd';
	char e = 'e';

	//无需char和int的转换,因此调用函数模板是更好的选择
	myPrint(d, e);  //4 若函数模板可实现更好的匹配,则优先调用函数模板
}

int main()
{
	test01();
}

调用普通函数
调用函数模板
调用重载的函数模板
调用函数模板

模板的重载

可以为特定的数据类型(如数组、类等)提供具体化的模板
关键语句

template<>
bool myCompare(Person & p1, Person& p2)
#include<iostream>
using namespace std;

class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	string m_Name;
	int m_Age;
};

//判断两个数据是否相等
template<class T>
bool myCompare(T& a, T& b)
{
	if (a == b)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//利用具体化Person的版本实现代码,具体化优先调用
template<>
bool myCompare(Person & p1, Person& p2)
{
	if ((p1.m_Age == p2.m_Age) && (p1.m_Name == p2.m_Name))
	{
		return true;
	}
	else
	{
		return false;
	}
}

void test01()
{
	int a = 10;
	int b = 10;

	bool ret = myCompare(a, b);

	if (ret)
	{
		cout << "a = b" << endl;
	}
	else
	{
		cout << "a != b" << endl;
	}
}

void test02()
{
	Person p1("Tom", 10);
	Person p2("Tom", 10);

	bool ret = myCompare(p1, p2);

	if (ret)
	{
		cout << "p1 = p2" << endl;
	}
	else
	{
		cout << "p1 != p2" << endl;
	}
}

int main()
{
	test01();

	test02();
}

a = b
p1 = p2

类模板

作用:建立一个通用类,类中的成员数据类型可以不具体指定,用一个虚拟的类型表示
语法:template<typename T>,下面写类

类模板语法

#include<iostream>
using namespace std;

//类模板
template<class NameType, class AgeType>
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		m_Name = name;
		m_Age = age;
	}

	void showInfo()
	{
		cout << "name = " << m_Name << endl;
		cout << "age = " << m_Age << endl;
	}

	NameType m_Name;
	AgeType m_Age;
};

void test01()
{
	Person<string, int> p1("Tom", 10);

	p1.showInfo();

}

int main()
{
	test01();
}

name = Tom
age = 10

类模板与函数模板的区别

1 类模板没有自动类型推导的使用方式
2 类模板在模板参数列表中可以有默认参数

#include<iostream>
using namespace std;


template<class NameType, class AgeType=int>  //2 类模板在模板参数列表中可以有默认参数
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		m_Name = name;
		m_Age = age;
	}

	void showInfo()
	{
		cout << "name = " << m_Name << endl;
		cout << "age = " << m_Age << endl;
	}

	NameType m_Name;
	AgeType m_Age;
};

void test01()
{
	//Person p("Tom", 10);  //1 无法进行自动类型推导
	Person<string, int> p("Tom", 10);

	p.showInfo();
}

void test02()
{
	Person<string> p("Jack", 18);  //2 类模板在模板参数列表中可以有默认参数

	p.showInfo();
}

int main()
{
	test01();

	test02();
}

name = Tom
age = 10
name = Jack
age = 18

类模板中成员函数创建时机

普通类中的成员函数一开始就可以创建
类模板中的成员函数在调用时才创建

#include<iostream>
using namespace std;

class Person1
{
public:
	void showPerson1()
	{
		cout << "Person1 show" << endl;
	}
};

class Person2
{
public:
	void showPerson2()
	{
		cout << "Person2 show" << endl;
	}
};

template<class T>
class Myclass
{
public:

	//类模板中的成员函数
	void func1()
	{
		obj.showPerson1();
	}

	void func2()
	{
		obj.showPerson2();
	}

	T obj;

};

void test01()
{
	Myclass<Person1> m;
	m.func1();

	//m.func2();  //编译出错,说明函数调用才会创建成员函数
}

int main()
{
	test01();
}

Person1 show

类模板对象做函数参数

1 指定传入的类型(最常用)
2 参数模板化
3 整个类模板化

#include<iostream>
using namespace std;

template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age)
	{
		m_Name = name;
		m_Age = age;
	}

	void showInfo()
	{
		cout << "name = " << m_Name << endl;
		cout << "age = " << m_Age << endl;
	}

	T1 m_Name;
	T2 m_Age;
};

//1 指定传入类型
void printPerson1(Person<string, int>& p)
{
	p.showInfo();
}

void test01()
{
	Person<string, int> p("Tom", 10);
	printPerson1(p);

}

//2 参数模板化
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
	p.showInfo();
}

void test02()
{
	Person<string, int> p("Jack", 18);
	printPerson2(p);
}

//3 整个类模板化
template<class T>
void printPerson3(T &p)
{
	p.showInfo();
}

void test03()
{
	Person<string, int> p("Amy", 25);
	printPerson3(p);
}

int main()
{
	cout << "指定传入类型" << endl;
	test01();
	cout << "参数模板化" << endl;
	test02();
	cout << "整个类模板化" << endl;
	test03();
}

指定传入类型
name = Tom
age = 10
参数模板化
name = Jack
age = 18
整个类模板化
name = Amy
age = 25

类模板与继承

1 若子类继承的父类是一个类模板,则子类在声明时需要指出父类T的类型,否则编译器无法给子类分配内存(因为不知道T的数据类型
2 若想灵活指定父类的T类型,子类也需要为类模板

#include<iostream>
using namespace std;

template<class T>
class Base
{
	T m;
};

class Son1 :public Base<int>  //指定T类型  
{

};

void test01()
{
	Son1 s1;
}

//若想灵活指定父类的T类型,子类也需要为类模板
template<class T1, class T2>
class Son2 :public Base<T2>
{
public:
	Son2()
	{
		cout << "Son2(T1)的类型: " << typeid(T1).name() << endl;
		cout << "Base(T2)的类型: " << typeid(T2).name() << endl;
	}
	T1 obj;
};

void test02()
{
	Son2<int, char> s2; //Son2的obj为int, Base的obj为char
}


int main()
{
	test01();

	test02();
}

Son2(T1)的类型: int
Base(T2)的类型: char

类模板成员函数类外实现

类模板中成员函数类外实现时,需要加上模板参数列表

//成员函数类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	m_Name = name;
	m_Age = age;
}

template<class T1, class T2>
void Person<T1, T2>::showInfo()
{
	cout << "name = " << m_Name << endl;
	cout << "age = " << m_Age << endl;
}
#include<iostream>
using namespace std;

template<class T1, class T2>
class Person
{
public:

	Person(T1 name, T2 age);

	void showInfo();

	T1 m_Name;
	T2 m_Age;
};

//成员函数类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	m_Name = name;
	m_Age = age;
}

template<class T1, class T2>
void Person<T1, T2>::showInfo()
{
	cout << "name = " << m_Name << endl;
	cout << "age = " << m_Age << endl;
}

void test01()
{
	Person<string, int> p("Tom", 18);
	p.showInfo();
}

int main()
{
	test01();
}

name = Tom
age = 18

类模板分文件编写

背景:类模板成员函数创建时机是在调用阶段,导致分文件编写时,链接不到
解决方法
1 直接包含.cpp源文件,将原来的#include "person.h"改为#include “person.cpp”
2 将声明和实现都写到一个文件里,并更改后缀为.hpp(约定俗成)

person.hpp
#pragma once
#include<iostream>

using namespace std;

template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age);

	void showInfo();

	T1 m_Name;
	T2 m_Age;
};

template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age)
{
	m_Name = name;
	m_Age = age;
}

template<class T1, class T2>
void Person<T1, T2>::showInfo()
{
	cout << "name = " << m_Name << endl;
	cout << "age = " << m_Age << endl;
}
main.cpp
#include<iostream>
#include "person.hpp"

using namespace std;

void test01()
{
	Person<string, int> p("Tom", 10);
	p.showInfo();
}

int main()
{
	test01();
}

name = Tom
age = 10

类模板与友元

全局函数类内实现——直接在类内声明友元
全局函数类外实现——需要提前让编译器知道全局函数的存在

#include<iostream>

using namespace std;

template<class T1, class T2>
class Person
{
	//1 全局函数, 类内实现
	friend void printInfo(Person<T1, T2>& p)
	{
		cout << "类内实现" << endl;
		cout << "name = " << p.m_Name << endl;
		cout << "age = " << p.m_Age << endl;
	}

public:
	Person(T1 name, T2 age)
	{
		m_Name = name;
		m_Age = age;
	}
private:

	T1 m_Name;
	T2 m_Age;
};

//1 全局函数, 类内实现
void test01()
{
	Person<string, int> p("Tom", 18);
	printInfo(p);
}

int main()
{
	test01();

}

类内实现
name = Tom
age = 18

类模板案例——通用数组类

image.png

myArray.hpp
#pragma once
#include<iostream>

using namespace std;

template<class T>
class MyArray
{
public:
	MyArray(int capacity)
	{
		this->m_Capacity = capacity;
		this->m_Size = 0;
		//对于Person自定义类,记得提供默认拷贝构造
		pAddress = new T[this->m_Capacity];
	}

	MyArray(const MyArray& arr)
	{
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		//深拷贝
		this->pAddress = new T[this->m_Capacity];

		for (int i = 0; i < this->m_Size; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
	}

	//operator= 防止浅拷贝问题,注意这里是两个MyArray类的=
	MyArray& operator=(const MyArray&arr)
	{
		if (this->pAddress != NULL)
		{
			delete[] this->pAddress;
			this->m_Capacity = 0;
			this->m_Size = 0;
		}

		//深拷贝
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		this->pAddress = new T[arr.m_Capacity];
		for (int i = 0; i < m_Size; i++)
		{
			pAddress[i] = arr.pAddress[i];
		}

		return *this;
	}

	//尾插法
	void push_Back(const T& val)
	{
		if (this->m_Size == this->m_Capacity)
		{
			return;
		}
		this->pAddress[this->m_Size] = val;  //数组末尾,插入数据
		this->m_Size += 1;  //更新数组大小
	}

	//尾删法
	void pop_Back()
	{
		if (this->m_Size == 0)
		{
			return;
		}
		this->m_Size -= 1;
	}
    
    //这是类内的方法
	//通过下标方式访问数组中的元素, arr[0] = 100
	T& operator[](int index)
	{
		return this->pAddress[index];
	}

	//返回数组容量
	int get_Capacity()
	{
		return this->m_Capacity;
	}

	//返回数组大小
	int get_Size()
	{
		return this->m_Size;
	}


	~MyArray()
	{
		if (pAddress != NULL)
		{
			delete[] this->pAddress;
			this->pAddress = NULL;
			this->m_Capacity = 0;
			this->m_Size = 0;
		}
	}

private:
	T* pAddress;  //指针指向堆区开辟的真实数组

	int m_Capacity;  //数组容量

	int m_Size;  //数组大小
};
main.cpp
#include<iostream>
#include "myArray.hpp"

using namespace std;

class Person
{
public:
	//注意这里要自己提供默认拷贝构造
	Person()
	{

	}

	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;

	}

	string m_Name;
	int m_Age;
};

//输出整型数组
void printIntInfo(MyArray<int>&arr)
{
	int len = arr.get_Size();

	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}

	cout << endl;
}

//输出Person数组
void printPersonInfo(MyArray<Person>& p)
{
	int len = p.get_Size();
	for (int i = 0; i < len; i++)
	{
		cout << "第" << i << "位信息" << endl;
		cout << "name = " << p[i].m_Name << endl;
		cout << "age = " << p[i].m_Age << endl;
	}
}

//测试整型数据类型
void test01()
{
	MyArray<int>arr1(5);

	for (int i = 0; i < 5; i++)
	{
		//尾插
		arr1.push_Back(i);
	}

	cout << "arr1的打印输出如下: " << endl;
    
    //由于传入的是MyArray类的实例对象arr1,因此若想要实现arr1[i]的访问,需要重载运算符
	printIntInfo(arr1);

	cout << "arr1 capacity = " << arr1.get_Capacity() << endl;
	cout << "arr1 size = " << arr1.get_Size() << endl;

	cout << "-----------------" << endl;

	//拷贝构造调用
	MyArray<int>arr2(arr1);

	cout << "arr2的打印输出如下: " << endl;

	printIntInfo(arr2);

	cout << "arr2 capacity = " << arr2.get_Capacity() << endl;
	cout << "arr2 size = " << arr2.get_Size() << endl;

	//尾删
	arr2.pop_Back();

	cout << "arr2(尾删后)的打印输出如下: " << endl;

	printIntInfo(arr2);

	cout << "arr2(尾删后) capacity = " << arr2.get_Capacity() << endl;
	cout << "arr2(尾删后) size = " << arr2.get_Size() << endl;

	cout << "-----------------" << endl;

}

//测试自定义数据类型

void test02()
{
	MyArray<Person> p(10);

	Person p1("Tom", 10);
	Person p2("Jack", 15);
	Person p3("Mike", 20);
	Person p4("Amy", 25);
	Person p5("Anki", 30);

	//尾插法
	p.push_Back(p1);
	p.push_Back(p2);
	p.push_Back(p3);
	p.push_Back(p4);
	p.push_Back(p5);

	//输出信息
	printPersonInfo(p);

	cout << "p capacity = " << p.get_Capacity() << endl;
	cout << "p size = " << p.get_Size() << endl;
}

int main()
{
	test01();

	test02();
}

arr1的打印输出如下:
0 1 2 3 4
arr1 capacity = 5
arr1 size = 5
-----------------
arr2的打印输出如下:
0 1 2 3 4
arr2 capacity = 5
arr2 size = 5
arr2(尾删后)的打印输出如下:
0 1 2 3
arr2(尾删后) capacity = 5
arr2(尾删后) size = 4
-----------------0位信息
name = Tom
age = 101位信息
name = Jack
age = 152位信息
name = Mike
age = 203位信息
name = Amy
age = 254位信息
name = Anki
age = 30
p capacity = 10
p size = 5

STL

C++的面向对象泛型编程的思想,目的都是提高代码的复用性
STL就是提供一套标准模板,来提高代码的复用性

基本概念

  • STL:Standard Template Library,标准模板库
  • STL分为:容器(container)、算法(algorithm)、迭代器(iterator)
  • 容器算法之间,通过迭代器进行连接
  • STL几乎所有代码都采用了模板类或者模板函数

六大组件

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

容器

各种数据结构,包括vector、list、deque、set、map
分为序列式容器关联式容器

  • 序列式容器:强调值的排序,每个元素均有固定的位置
  • 关联式容器:二叉树结构

算法

各种常用算法,包括sort、find、copy、for_each等

迭代器

容器和算法之间的胶合剂
算法,要通过迭代器,才能访问容器中的元素

仿函数

行为类似函数,可作为算法的某种策略

适配器

用来修饰容器或者迭代器或者仿函数接口

空间配置器

负责空间的配置和管理

实例1——vector存放内置数据类型

容器:vector
算法:for_each
迭代器:vector<int>::iterator

#include<iostream>
#include <vector>
#include<algorithm> //标准算法的头文件

using namespace std;

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

void test01()
{
	//创建了一个vector容器,可视之为数组
	vector<int> v;

	//向容器中插入数据
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);

	//第一种遍历方式
	//通过迭代器访问容器中的数据
	vector<int>::iterator itBegin = v.begin(); //起始迭代器
	vector<int>::iterator itEnd = v.end();  //结束迭代器

	cout << "第一种遍历方式" << endl;
	while (itBegin != itEnd)
	{
		cout << *itBegin << endl;
		itBegin += 1;
	}

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

	cout << "第三种遍历方式" << endl;
	//第三种遍历方式,利用STL提供的遍历算法,回调机制
	for_each(v.begin(), v.end(), myPrint);

}

int main()
{
	test01();
}

第一种遍历方式
10
20
30
40
50
第二种遍历方式
10
20
30
40
50
第三种遍历方式
10
20
30
40
50

实例2——vector存放自定义数据类型

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

using namespace std;

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

	string m_Name;
	int m_Age;
};

void test01()
{
	cout << "test01" << endl;
	vector<Person> v;

	Person p1("Tom", 18);
	Person p2("Mike", 22);
	Person p3("Amy", 26);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);

	//*it的数据类型为Person
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "name: " << (*it).m_Name << " age: " << (*it).m_Age << endl;
		cout << "name: " << it->m_Name << " age: " << it->m_Age << endl;
	}
}

void test02()
{
	cout << "test02" << endl;
	vector<Person*> v;

	Person p1("Tom", 18);
	Person p2("Mike", 22);
	Person p3("Amy", 26);

	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);

    //*it的数据类型为Person*
	for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "name: " << (**it).m_Name << " age: " << (**it).m_Age << endl;
		cout << "name: " << (*it)->m_Name << " age: " << (*it)->m_Age << endl;
	}
}


int main()
{
	test01();

	test02();
}

test01
name: Tom age: 18
name: Tom age: 18
name: Mike age: 22
name: Mike age: 22
name: Amy age: 26
name: Amy age: 26
test02
name: Tom age: 18
name: Tom age: 18
name: Mike age: 22
name: Mike age: 22
name: Amy age: 26
name: Amy age: 26

实例3——容器嵌套容器

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

using namespace std;

void test01()
{
	vector<vector<int>> v;

	//内层容器
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;

	//内层容器添加数据
	for (int i = 0; i < 3; i++)
	{
		v1.push_back(i + 1);
		v2.push_back(i + 2);
		v3.push_back(i + 3);
	}

	//外层容器添加数据
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);

	//外层容器,遍历所有数据
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
	{
		for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
		{
			cout << *vit << " ";
		}
		cout << endl;
	}

}

int main()
{
	test01();
}

1 2 3
2 3 4
3 4 5

string容器

string的本质是一个类,类内封装了char*

构造函数

#include<iostream>
#include <algorithm>

using namespace std;

void test01()
{

	//默认构造 string()
	string s1;

	//字符串s初始化 string(const char* s)
	const char* str = "Hello World!";
	string s2(str);

	cout << "s2 = " << s2 << endl;

	//拷贝构造  string(const string &s)
	string s3(s2);

	cout << "s3 = " << s3 << endl;

	//n个字符c初始化  string(int n, char c)

	string s4(10, 'a');

	cout << "s4 = " << s4 << endl;

}

int main()
{
	test01();
}

s2 = Hello World!
s3 = Hello World!
s4 = aaaaaaaaaa

赋值操作

image.png

#include<iostream>
#include <algorithm>

using namespace std;

void test01()
{
	string s1;
	s1 = "Hello World!";
	cout << "s1 = " << s1 << endl;

	string s2;
	s2 = s1;
	cout << "s2 = " << s2 << endl;

	string s3;
	s3 = 'a';
	cout << "s3 = " << s3 << endl;

	string s4;
	s4.assign("Hello World");
	cout << "s4 = " << s4 << endl;

	string s5;
	s5.assign("Hello World", 5);
	cout << "s5 = " << s5 << endl;

	string s6;
	s6.assign(s4);
	cout << "s6 = " << s6 << endl;

	string s7;
	s7.assign(10, 'a');
	cout << "s7 = " << s7 << endl;
}

int main()
{
	test01();
}

s1 = Hello World!
s2 = Hello World!
s3 = a
s4 = Hello World
s5 = Hello
s6 = Hello World
s7 = aaaaaaaaaa

字符串拼接

image.png

#include<iostream>
#include <algorithm>

using namespace std;

void test01()
{

	string s1;
	s1 = "Hello";

	s1 += " World";
	cout << "s1 = " << s1 << endl;

	s1 += "!";
	cout << "s1 = " << s1 << endl;

	string s2;
	s2 = "Yes!";

	s1 += s2;
	cout << "s1 = " << s1 << endl;

	string s3;
	s3 = "I";

	s3.append(" love");
	cout << "s3 = " << s3 << endl;

	s3.append(" you!y", 5);
	cout << "s3 = " << s3 << endl;

	s3.append(s2);
	cout << "s3 = " << s3 << endl;

}

int main()
{
	test01();
}

s1 = Hello World
s1 = Hello World!
s1 = Hello World!Yes!
s3 = I love
s3 = I love you!
s3 = I love you!Yes!

查找和替换

find、replace
image.png

#include<iostream>
#include <string>

using namespace std;

//查找
void test01()
{

	string s1;
	s1 = "Hello World!";

    //找到,返回index,否则返回-1
	int pos1 = s1.find('o');
	cout << "pos1 = " << pos1 << endl;

	//从右往左查找
	int pos2 = s1.rfind('o');
	cout << "pos2 = " << pos2 << endl;
}

//替换
void test02()
{
	string s = "Hello World!";

	s.replace(6, 11, "Mike");

	cout << "s = " << s << endl;
}

int main()
{
	test01();

	test02();
}

pos1 = 4
pos2 = 7
s = Hello Mike

字符串比较

image.png

#include<iostream>
#include <string>

using namespace std;

void test01()
{

	string s1;
	s1 = "hello";

	string s2;
	s2 = "hello";

	//s1=s2
	int ret1 = s1.compare(s2);
	cout << "s1=s2: " << ret1 << endl;

	string s3;
	s3 = "aello";

	//s1>s3
	int ret2 = s1.compare(s3);
	cout << "s1>s3: " << ret2 << endl;

	string s4;
	s4 = "zello";

	//s1<s4
	int ret3 = s1.compare(s4);
	cout << "s1<s4: " << ret3 << endl;
}


int main()
{
	test01();

}

s1=s2: 0
s1>s3: 1
s1<s4: -1

字符存取

image.png

#include<iostream>
#include <string>

using namespace std;

void test01()
{

	string s1;
	s1 = "hello";

	//1 []访问单个字符
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;

	//2 at方式访问单个字符
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1.at(i) << " ";
	}
	cout << endl;

	//3 修改单个字符,注意在python中无法修改字符串
	s1[0] = 'a';
	cout << s1 << endl;

	s1.at(0) = 'h';
	cout << s1 << endl;
}


int main()
{
	test01();

}

h e l l o
h e l l o
aello
hello

插入和删除

image.png

#include<iostream>
#include <string>

using namespace std;

void test01()
{

	string s1;
	s1 = "hello";

	//插入
	s1.insert(5, " World");

	cout << s1 << endl;

	//删除
	s1.erase(5, s1.size());

	cout << s1 << endl;

}


int main()
{
	test01();

}

hello World
hello

字串获取

image.png

#include<iostream>
#include <string>

using namespace std;

void test01()
{

	string s1;
	s1 = "hello";

	string subStr = s1.substr(0, 2);

	cout << "subStr = " << subStr << endl;

}

void test02()
{
	string email = "hello@sina.com";

	int pos = email.find('@');

	cout << "pos = " << pos << endl;

	//左闭右开
	string userName = email.substr(0, pos);

	cout << "userName = " << userName << endl;
}


int main()
{
	test01();

	test02();

}

subStr = he
pos = 5
userName = hello

vector容器

功能:单端数组,且可以动态扩展,vector容器的迭代器是支持随机访问的迭代器
动态扩展:不是在原空间之后续接新空间,而是寻找更大的内容空间,然后将原数据拷贝到新空间,释放原空间
image.png

构造函数

image.png

#include<iostream>
#include <vector>

using namespace std;

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

void test01()
{
	//默认构造
	vector<int> v1;

	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}

	printVector(v1);

	//通过区间方式进行构造
	vector<int> v2(v1.begin(), v1.end());
	printVector(v2);

	//n个元素方式进行构造
	vector<int> v3(5, 1);
	printVector(v3);

	//拷贝构造
	vector<int> v4(v1);
	printVector(v4);

}

int main()
{
	test01();

}

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

赋值操作

image.png

#include<iostream>
#include <vector>

using namespace std;

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

void test01()
{
	//默认构造
	vector<int> v1;

	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}

	printVector(v1);

	//operator=
	vector<int> v2 = v1;
	printVector(v2);

	//assign
	vector<int> v3;
	v3.assign(v1.begin(), v1.end());
	printVector(v3);

	vector<int> v4;
	v4.assign(10, 1);
	printVector(v4);

}

int main()
{
	test01();

}

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

容量和大小

image.png

#include<iostream>
#include <vector>

using namespace std;

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

void test01()
{
	vector<int> v1;

	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}

	printVector(v1);

	if (v1.empty())
	{
		cout << "v1为空" << endl;
	}
	else
	{
		cout << "v1 不为空" << endl;
		cout << "v1 Capacity: " << v1.capacity() << endl;
		cout << "v1 Size: " << v1.size() << endl;
	}

	//resize方法, 默认用0填充, 也可以指定填充值,如1
	v1.resize(15, 1);
	printVector(v1);

	//超出部分被删除
	v1.resize(5);
	printVector(v1);

}

int main()
{
	test01();

}

0 1 2 3 4 5 6 7 8 9
v1 不为空
v1 Capacity: 13
v1 Size: 10
0 1 2 3 4 5 6 7 8 9 1 1 1 1 1
0 1 2 3 4

插入和删除

image.png

#include<iostream>
#include <vector>

using namespace std;

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

void test01()
{
	vector<int> v1;

	for (int i = 0; i < 10; i++)
	{
		//尾插法
		v1.push_back(i);
	}

	printVector(v1);

	//尾删法
	v1.pop_back();
	printVector(v1);

	//插入, 注意第一个参数为迭代器
	v1.insert(v1.begin(), 100);
	printVector(v1);

	//插入n个元素
	v1.insert(v1.begin(), 2, 10);
	printVector(v1);

	//删除
	v1.erase(v1.begin());
	printVector(v1);

	//清空
	//v1.erase(v1.begin(), v1.end());
	v1.clear();
	printVector(v1);

}

int main()
{
	test01();

}

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

数据存取

image.png

#include<iostream>
#include <vector>

using namespace std;

void test01()
{
	vector<int> v1;

	for (int i = 0; i < 10; i++)
	{
		//尾插法
		v1.push_back(i);
	}

	//利用[]方式来访问元素
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	//利用at方式来访问元素
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1.at(i) << " ";
	}
	cout << endl;

	cout << "first element: " << v1.front() << endl;

	cout << "last element: " << v1.back() << endl;

}

int main()
{
	test01();

}

0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
first element: 0
last element: 9

互换容器

除了互换元素,还有收缩内存空间的作用
image.png

#include<iostream>
#include <vector>

using namespace std;

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

void test01()
{
	vector<int> v1;

	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}

	vector<int> v2;
	for (int i = 9; i > -1; i--)
	{
		v2.push_back(i);
	}

	cout << "交换前" << endl;
	printVector(v1);
	printVector(v2);

	v1.swap(v2);
	cout << "交换后" << endl;
	printVector(v1);
	printVector(v2);

	cout << "----------" << endl;
}

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

	cout << "v capacity = " << v.capacity() << endl;
	cout << "v size = " << v.size() << endl;

	//造成大量空间浪费
	v.resize(3);
	cout << "v capacity = " << v.capacity() << endl;
	cout << "v size = " << v.size() << endl;

	//swap收缩内存空间
	//vector<int>(v): 匿名对象,且根据当前已用元素个数(即3个元素)来初始容量
	//swap相当于两个对象的指针交换
	//匿名对象在当前行执行之后,会自动回收内存
	vector<int>(v).swap(v);
	cout << "v capacity = " << v.capacity() << endl;
	cout << "v size = " << v.size() << endl;
}

int main()
{
	test01();

	test02();

}

交换前
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
交换后
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
----------
v capacity = 138255
v size = 100000
v capacity = 138255
v size = 3
v capacity = 3
v size = 3

预留空间

作用:减少vector在动态扩展容量时的扩展次数(对于数据量较大的情况)
注意**:vector是动态扩展**,即当空间不够时,会重新寻找另一块更大的内存空间,然后将原数据拷贝到新空间,释放原空间;因此vector的首地址会不断变化
image.png

#include<iostream>
#include <vector>

using namespace std;

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

void test01()
{
	vector<int> v1;

	int num = 0;  //记录开辟内存总次数
	int* p = NULL;
	for (int i = 0; i < 100000; i++)
	{
		v1.push_back(i);
		if (p != &v1[0])
		{
			p = &v1[0];
			num += 1;
		}
	}

	//分配了30次空间
	cout << "num = " << num << endl;

	cout << "-------------" << endl;

}

void test02()
{
	vector<int> v1;

	//利用reserve预留空间
	v1.reserve(100000);

	int num = 0;  //记录开辟内存总次数
	int* p = NULL;
	for (int i = 0; i < 100000; i++)
	{
		v1.push_back(i);
		if (p != &v1[0])
		{
			p = &v1[0];
			num += 1;
		}
	}

	//只分配了1次空间
	cout << "num = " << num << endl;

}

int main()
{
	test01();

	test02();

}

num = 30
-------------
num = 1

deque容器

功能:双端数组,可以对头端进行插入删除操作,因此对头部的插入删除速度比vector快,但访问元素的速度比vector慢,deque容器的迭代器也是支持随机访问
image.png
内部原理:中控器,维护每段缓冲区的内容,缓冲区中存放真实数据,中控器维护的是每个缓冲区的地址;由于deque容器需要通过中控器来访问数据,因此访问速度比vector慢
image.png

构造函数

image.png

#include<iostream>
#include<deque>

using namespace std;

void printDeque(const deque<int>& d)
{
	//使用const_iterator, 防止修改原有数据
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{

	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}

	printDeque(d1);

	deque<int>d2(d1.begin(), d1.end());

	printDeque(d2);

	deque<int> d3(10, 1);

	printDeque(d3);

	deque<int> d4(d1);

	printDeque(d4);
}

int main()
{
	test01();
}

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

赋值操作

image.png

#include<iostream>
#include<deque>

using namespace std;

void printDeque(const deque<int>& d)
{
	//使用const_iterator, 防止修改原有数据
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{

	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}

	printDeque(d1);

	//operator=赋值
	deque<int>d2 = d1;

	printDeque(d2);

	//assign
	deque<int>d3;
	d3.assign(d1.begin(), d1.end());

	printDeque(d3);

	deque<int>d4;
	d4.assign(10, 1);
	printDeque(d4);
}

int main()
{
	test01();
}

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

大小操作

注意deque没有容量的概念
image.png

#include<iostream>
#include<deque>

using namespace std;

void printDeque(const deque<int>& d)
{
	//使用const_iterator, 防止修改原有数据
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{

	deque<int> d1;
	for (int i = 0; i < 10; i++)
	{
		d1.push_back(i);
	}

	printDeque(d1);

	if (d1.empty())
	{
		cout << "deque为空" << endl;
	}
	else
	{
		cout << "deque不为空" << endl;
		cout << "d1 size = " << d1.size() << endl;
	}

	//resize
	d1.resize(15, 1);
	printDeque(d1);

	d1.resize(5);
	printDeque(d1);

}

int main()
{
	test01();
}

0 1 2 3 4 5 6 7 8 9
deque不为空
d1 size = 10
0 1 2 3 4 5 6 7 8 9 1 1 1 1 1
0 1 2 3 4

插入和删除

注意插入和删除:提供的位置是迭代器
image.png

#include<iostream>
#include<deque>

using namespace std;

void printDeque(const deque<int>& d)
{
	//使用const_iterator, 防止修改原有数据
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void test01()
{
	deque<int> d1;

	//尾插
	d1.push_back(10);
	d1.push_back(20);

	//头插
	d1.push_front(100);
	d1.push_front(200);

	printDeque(d1);  //[200, 100, 10, 20]

	//尾删
	d1.pop_back();

	printDeque(d1);  //[200, 100, 10]

	//头删
	d1.pop_front();

	printDeque(d1);  //[100, 10]

	cout << "--------------" << endl;

}

void test02()
{
	deque<int> d1;

	//尾插
	d1.push_back(10);
	d1.push_back(20);

	//头插
	d1.push_front(100);
	d1.push_front(200);

	printDeque(d1);  //[200, 100, 10, 20]

	//insert插入
	d1.insert(d1.begin(), 1000);

	printDeque(d1);  //[1000, 200, 100, 10, 20]

	d1.insert(d1.begin(), 2, 500);

	printDeque(d1);  //[500, 500, 1000, 200, 100, 10, 20]

	//区间insert插入
	deque<int>d2;

	d2.push_back(1);
	d2.push_back(2);
	d2.push_back(3);

	d1.insert(d1.begin(), d2.begin(), d2.end());

	printDeque(d1);  //[1, 2, 3, 500, 500, 1000, 200, 100, 10, 20]

	cout << "--------------" << endl;
}

void test03()
{
	deque<int> d1;

	//尾插
	d1.push_back(10);
	d1.push_back(20);

	//头插
	d1.push_front(100);
	d1.push_front(200);

	printDeque(d1);  //[200, 100, 10, 20]

	//删除第二个元素
	d1.erase(d1.begin()+1);

	printDeque(d1);  //[200, 10, 20]

	//区间删除, 清空操作
	d1.erase(d1.begin(), d1.end());
    //d1.clear();
	printDeque(d1);
}

int main()
{
	test01();

	test02();

	test03();
}

200 100 10 20
200 100 10
100 10
--------------
200 100 10 20
1000 200 100 10 20
500 500 1000 200 100 10 20
1 2 3 500 500 1000 200 100 10 20
--------------
200 100 10 20
200 10 20

数据存取

image.png

#include<iostream>
#include<deque>

using namespace std;


void test01()
{
	deque<int> d1;

	//尾插
	d1.push_back(10);
	d1.push_back(20);

	//头插
	d1.push_front(100);
	d1.push_front(200);

	//通过[]方式访问元素
	for (int i = 0; i < d1.size(); i++)
	{
		cout << d1[i] << " ";
	}
	cout << endl;

	//通过at方式访问元素
	for (int i = 0; i < d1.size(); i++)
	{
		cout << d1.at(i) << " ";
	}
	cout << endl;

	cout << "d1 front: " << d1.front() << endl;
	cout << "d1 back: " << d1.back() << endl;
}


int main()
{
	test01();
}

200 100 10 20
200 100 10 20
d1 front: 200
d1 back: 20

排序

image.png

#include<iostream>
#include<deque>
#include<algorithm>

using namespace std;

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


void test01()
{
	deque<int> d1;

	//尾插
	d1.push_back(10);
	d1.push_back(20);

	//头插
	d1.push_front(100);
	d1.push_front(200);

	printDeque(d1);

	//排序
	sort(d1.begin(), d1.end());

	printDeque(d1);
}


int main()
{
	test01();
}

200 100 10 20
10 20 100 200

案例——评委打分

image.png

#include<iostream>
#include<vector>
#include<deque>
#include<string>
#include<algorithm>
#include<ctime>
using namespace std;

class Person
{
public:
	Person(string name, int score)
	{
		this->m_Name = name;
		this->m_Score = score;
	}
	string m_Name;
	int m_Score;
};

void createPerson(vector<Person>& v)
{
	string nameSeed = "ABCDE";
	for (int i = 0; i < 5; i++)
	{
		string name = "";
		name += nameSeed[i];

		int score = 0;

		Person p(name, score);

		v.push_back(p);
	}
}

void setScore(vector<Person>& v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		//将评委的分数放到deque容器中
		deque<int>d;
		for (int i = 0; i < 10; i++)
		{
			int score = rand() % 41 + 60;  //60-100
			d.push_back(score);
		}

		//deque排序
		sort(d.begin(), d.end());

		//去除最高分和最低分
		d.pop_back();  //去除最高分
		d.pop_front();  //去除最低分

		//取平均分
		int sum = 0;
		for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
		{
			sum += *dit;
		}

		int avg = sum / d.size();

		//将平均分赋值到选手
		(*it).m_Score = avg;
	}
}

void showScore(vector<Person>& v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "Name: " << (*it).m_Name << " Score: " << (*it).m_Score << endl;
	}
}

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

	//创建5名选手
	vector<Person> v;
	createPerson(v);

	//打分
	setScore(v);

	//显示得分
	showScore(v);

}

Name: A Score: 81
Name: B Score: 78
Name: C Score: 83
Name: D Score: 79
Name: E Score: 85

stack容器

功能:栈,后进先出
image.png
image.png

#include<iostream>
#include<stack>


using namespace std;

void test01()
{
	stack<int>s;

	s.push(10);
	s.push(20);
	s.push(30);

	cout << "s size = " << s.size() << endl;
	while (!s.empty())
	{
		cout << s.top() << " ";
		s.pop();
	}
	cout << endl;

	cout << "s size = " << s.size() << endl;

}


int main()
{
	test01();
}

s size = 3
30 20 10
s size = 0

queue容器

image.png

#include<iostream>
#include<queue>

using namespace std;

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

void test01()
{
	queue<Person>q;

	Person p1("Tom", 18);
	Person p2("Mike", 25);
	Person p3("Amy", 28);

	q.push(p1);
	q.push(p2);
	q.push(p3);

	cout << "q size = " << q.size() << endl;

	while (!q.empty())
	{
		cout << "队头 Name = " << q.front().m_Name << " Age = " << q.front().m_Age << endl;
		cout << "队尾 Name = " << q.back().m_Name << " Age = " << q.back().m_Age << endl;
		cout << endl;
		q.pop();
	}

	cout << "q size = " << q.size() << endl;

}


int main()
{
	test01();
}

q size = 3
队头 Name = Tom Age = 18
队尾 Name = Amy Age = 28

队头 Name = Mike Age = 25
队尾 Name = Amy Age = 28

队头 Name = Amy Age = 28
队尾 Name = Amy Age = 28

q size = 0

list容器(链表)

功能:将数据进行链式存储
组成:由一系列结点组成,结点包括数据域(存储数据元素)和指针域(存储下一个结点地址)
优点:可以方便快速地进行插入删除,采用动态存储分配不会造成内存浪费和溢出
缺点:不支持随机访问(如数组按照索引访问那样),且空间占用更大(需要存储指针域
STL的链表是一个双向循环链表

构造函数

image.png

#include<iostream>
#include<list>

using namespace std;

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;

	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);

	printList(l1);

	//区间方式构造
	list<int>l2(l1.begin(), l1.end());

	printList(l2);

	//n个元素构造
	list<int>l3(3, 1);

	printList(l3);

	//拷贝构造
	list<int>l4(l1);

	printList(l4);
}


int main()
{
	test01();
}

10 20 30
10 20 30
1 1 1
10 20 30

赋值和交换

image.png

#include<iostream>
#include<list>

using namespace std;

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;

	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);

	printList(l1);

	//operator=赋值
	list<int>l2;
	l2 = l1;

	printList(l2);

	//区间赋值
	list<int>l3;
	l3.assign(l1.begin(), l1.end());

	printList(l3);

	//n个元素赋值
	list<int>l4;
	l4.assign(5, 1);

	printList(l4);

	cout << "--------------" << endl;
}

//交换
void test02()
{
	list<int>l1;

	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);

	list<int>l2;
	l2.assign(5, 1);

	cout << "-----交换前-----" << endl;

	printList(l1);
	printList(l2);

	//交换
	l1.swap(l2);

	cout << "-----交换后-----" << endl;

	printList(l1);
	printList(l2);
}

int main()
{
	test01();

	test02();
}


10 20 30
10 20 30
10 20 30
1 1 1 1 1
--------------
-----交换前-----
10 20 30
1 1 1 1 1
-----交换后-----
1 1 1 1 1
10 20 30

大小操作

image.png

#include<iostream>
#include<list>

using namespace std;

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;

	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);

	printList(l1);

	if (l1.empty())
	{
		cout << "l1为空" << endl;
	}
	else
	{
		cout << "l1不为空" << endl;
		cout << "l1 size = " << l1.size() << endl;
	}

	//resize操作
	l1.resize(10, 1);
	printList(l1);

	l1.resize(2);
	printList(l1);

}


int main()
{
	test01();

}

10 20 30
l1不为空
l1 size = 3
10 20 30 1 1 1 1 1 1 1
10 20

插入和删除

image.png
image.png

#include<iostream>
#include<list>

using namespace std;

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;

	//尾插
	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);

	//头插
	l1.push_front(100);
	l1.push_front(200);
	l1.push_front(300);

	printList(l1);  //300 200 100 10 20 30

	//尾删
	l1.pop_back();

	printList(l1);  //300 200 100 10 20

	//头删
	l1.pop_front();

	printList(l1);  //200 100 10 20

	//insert插入
	l1.insert(l1.begin(), 1000);

	printList(l1);  //1000 200 100 10 20

	//删除,根据索引
	l1.erase(l1.begin());

	printList(l1);  //200 100 10 20

	//移除,根据指定元素值
	l1.remove(10);

	printList(l1);  //200 100 20

	//清空
	l1.clear();

	printList(l1);
}


int main()
{
	test01();

}

300 200 100 10 20 30
300 200 100 10 20
200 100 10 20
1000 200 100 10 20
200 100 10 20
200 100 20
    

数据存取

由于list是链表,因此无法按索引index访问数据,不同于vector容器
image.png

#include<iostream>
#include<list>

using namespace std;

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;

	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);
	l1.push_back(40);

	cout << "l1 第一个元素: " << l1.front() << endl;
	cout << "l1 最后一个元素: " << l1.back() << endl;

	//迭代器不支持随机访问
	list<int>::iterator it = l1.begin();
	//支持双向
	it++;
	it--;
	//不支持随机访问
	//it = it + 1; 无法使用
}


int main()
{
	test01();

}

l1 第一个元素: 10
l1 最后一个元素: 40

反转和排序

image.png

#include<iostream>
#include<list>

using namespace std;

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;

	l1.push_back(10);
	l1.push_back(20);
	l1.push_back(30);
	l1.push_back(40);

	printList(l1);

	//反转
	l1.reverse();

	printList(l1);

	cout << "--------------" << endl;
}

void test02()
{
	list<int>l1;

	l1.push_back(10);
	l1.push_back(30);
	l1.push_back(20);
	l1.push_back(40);

	printList(l1);

	//默认排序,升序
	l1.sort();

	printList(l1);
}



int main()
{
	test01();

	test02();

}

10 20 30 40
40 30 20 10
--------------
10 30 20 40
10 20 30 40

排序案例

image.png

#include<iostream>
#include<list>
#include<ctime>

using namespace std;

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 createList(list<Person>& l)
{
	string nameSeed = "ABCDE";
	for (int i = 0; i < 5; i++)
	{
		string name = "";
		name += nameSeed[i];

		int age = rand() % 41 + 20;
		int height = rand() % 31 + 160;

		Person p(name, age, height);

		l.push_back(p);
	}
}

//打印信息
void printList(const list<Person>& l)
{
	for (list<Person>::const_iterator it = l.begin(); it != l.end(); it++)
	{
		cout << "Name = " << it->m_Name << " Age = " << it->m_Age << " Height = " << it->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;
}

int main()
{
	srand((unsigned int)time(NULL));

	list<Person> l;

	//创建人物
	createList(l);

	printList(l);

	cout << "----------------------" << endl;

	//自定义排序
	l.sort(comparePerson);

	printList(l);
}

Name = A Age = 50 Height = 187
Name = B Age = 24 Height = 181
Name = C Age = 39 Height = 168
Name = D Age = 51 Height = 189
Name = E Age = 24 Height = 169
----------------------
Name = B Age = 24 Height = 181
Name = E Age = 24 Height = 169
Name = C Age = 39 Height = 168
Name = A Age = 50 Height = 187
Name = D Age = 51 Height = 189

set/multiset容器

功能:所有元素在插入时会自动被排序
本质:属于关联式容器,底层结构使用二叉树实现
区别:set不允许重复元素,multiset允许重复元素
注1:set容器只有insert的方法,没有push_back的方法
注2:set容器的特点就是自动排序+去除重复元素

构造和赋值

image.png

#include<iostream>
#include<set>

using namespace std;

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(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(20);
	s1.insert(30);

	printSet(s1);

	//拷贝构造
	set<int> s2(s1);
	printSet(s2);

	//赋值
	set<int> s3;
	s3 = s1;
	printSet(s3);

}

int main()
{
	test01();
}

10 20 30 40
10 20 30 40
10 20 30 40

大小和交换

image.png

#include<iostream>
#include<set>

using namespace std;

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(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(30);

	printSet(s1);

	if (s1.empty())
	{
		cout << "s1 为空" << endl;
	}
	else
	{
		cout << "s1 不为空" << endl;
		cout << "s1 size = " << s1.size() << endl;
	}

}

//交换
void test02()
{
	set<int> s1;

	s1.insert(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(30);

	set<int> s2;
	s2.insert(100);
	s2.insert(400);
	s2.insert(300);
	s2.insert(200);

	cout << "-----交换前-----" << endl;

	printSet(s1);
	printSet(s2);

	//交换
	s1.swap(s2);

	cout << "-----交换后-----" << endl;

	printSet(s1);
	printSet(s2);
}

int main()
{
	test01();

	test02();
}

10 20 30 40
s1 不为空
s1 size = 4
-----交换前-----
10 20 30 40
100 200 300 400
-----交换后-----
100 200 300 400
10 20 30 40

插入和删除

image.png

#include<iostream>
#include<set>

using namespace std;

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(40);
	s1.insert(10);
	s1.insert(20);
	s1.insert(30);

	printSet(s1);  //10 20 30 40

	//删除
	s1.erase(s1.begin());  //注意删除的是10

	printSet(s1);

	s1.erase(30);

	printSet(s1);

	//清空
	//s1.erase(s1.begin(), s1.end());
	s1.clear();

	printSet(s1);

}


int main()
{
	test01();
}

10 20 30 40
20 30 40
20 40
    

查找和统计

注意find的返回值
image.png

#include<iostream>
#include<set>

using namespace std;

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(40);
	s1.insert(10);
	s1.insert(20);
	s1.insert(30);

	printSet(s1);  //10 20 30 40
    
    //注意find返回的是迭代器
	set<int>::iterator it = s1.find(30);

	if (it != s1.end())
	{
		cout << "找到元素: " << *it << endl;
	}
	else
	{
		cout << "找不到元素" << endl;
	}
}

//统计
void test02()
{
	set<int> s1;

	s1.insert(40);
	s1.insert(10);
	s1.insert(20);
	s1.insert(30);

	int num = s1.count(30);

	//对于set而言,统计结果非1即0,因为set不允许重复元素
	cout << "num = " << num << endl;

}


int main()
{
	test01();

	test02();
}

10 20 30 40
找到元素: 30
num = 1

set和multiset的区别

image.png

#include<iostream>
#include<set>

using namespace std;

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

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


void test01()
{
	set<int> s1;

	s1.insert(40);
	s1.insert(10);
	s1.insert(20);

	pair<set<int>::iterator, bool> res = s1.insert(20);

	if (res.second)
	{
		cout << "插入成功" << endl;
	}
	else
	{
		cout << "插入失败, 重复元素" << endl;
	}

	s1.insert(30);

	printSet(s1);  //10 20 30 40

	multiset<int> s2;

	s2.insert(40);
	s2.insert(10);
	s2.insert(20);
	s2.insert(20);
	s2.insert(30);

	printMultiset(s2);  //10 20 20 30 40

}


int main()
{
	test01();
}

插入失败, 重复元素
10 20 30 40
10 20 20 30 40

创建pair对组

image.png

#include<iostream>
#include<string>

using namespace std;

void test01()
{
	//第一种方式
	pair<string, int> p1("Tom", 20);

	cout << "Name = " << p1.first << " Age = " << p1.second << endl;

	//第二种方式
	pair<string, int> p2 = make_pair("Amy", 18);

	cout << "Name = " << p2.first << " Age = " << p2.second << endl;

}

int main()
{
	test01();
}

Name = Tom Age = 20
Name = Amy Age = 18

排序

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

class myCompare
{
public:
	//仿函数,注意后面加const
	bool operator()(int v1, int v2) const
	{
		//降序
		return v1 > v2;
	}
};
内置数据类型
#include<iostream>
#include<set>

using namespace std;


//set容器排序
class myCompare
{
public:
	//仿函数,注意后面加const
	bool operator()(int v1, int v2) const
	{
		//降序
		return v1 > v2;
	}
};

void test01()
{
	//默认排序为升序
	set<int> s1;

	s1.insert(20);
	s1.insert(10);
	s1.insert(30);
	s1.insert(50);

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

	//指定排序为降序
	set<int,myCompare> s2;

	s2.insert(20);
	s2.insert(10);
	s2.insert(30);
	s2.insert(50);

	for (set<int, myCompare>::iterator it = s2.begin(); it != s2.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

int main()
{
	test01();
}

10 20 30 50
50 30 20 10
自定义数据类型
#include<iostream>
#include<set>

using namespace std;

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

//set容器排序
class myCompare
{
public:
	//仿函数
	bool operator()(const Person &p1, const Person &p2) const
	{
		//按照年龄升序
		return p1.m_Age < p2.m_Age;
	}
};

void test01()
{
	//根据年龄升序
	set<Person, myCompare> s;

	Person p1("Tom", 30);
	Person p2("Mike", 18);
	Person p3("Amy", 25);

	s.insert(p1);
	s.insert(p2);
	s.insert(p3);

	for (set<Person, myCompare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << "Name = " << it->m_Name << " Age = " << it->m_Age << endl;
	}

}

int main()
{
	test01();
}

Name = Mike Age = 18
Name = Amy Age = 25
Name = Tom Age = 30

map/mulltimap容器

功能:map的所有元素都是pair键值对(key, value)的形式,且所有元素会根据元素的key来自动排序
本质:map/mulltimap容器属于关联式容器,底层结构使用二叉树实现
优点:可以根据key值快速找到value值
区别:map不允许重复key值,multimap允许重复key值

构造和赋值

image.png
注意下面的代码段

//默认构造
map<int, int> m;
m.insert(pair<int, int>(1, 10)); //key=1, value=10
#include<iostream>
#include<map>

using namespace std;

void printMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
	cout << endl;
}

void test01()
{
	//默认构造
	map<int, int> m;

	m.insert(pair<int, int>(1, 10)); //key=1, value=10
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(4, 40));

	printMap(m);

	//拷贝构造
	map<int, int> m2(m);

	printMap(m2);

	//赋值
	map<int, int> m3 = m2;

	printMap(m3);

}

int main()
{
	test01();
}

key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

大小和交换

image.png

#include<iostream>
#include<map>

using namespace std;

void printMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
	cout << endl;
}

//大小
void test01()
{
	map<int, int> m;

	m.insert(pair<int, int>(1, 10)); 
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(4, 40));

	if (m.empty())
	{
		cout << "m为空" << endl;
	}
	else
	{
		cout << "m不为空" << endl;
		cout << "m size = " << m.size() << endl;
	}
}

//交换
void test02()
{
	map<int, int> m1;
	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(4, 40));

	map<int, int> m2;
	m2.insert(pair<int, int>(1, 100));
	m2.insert(pair<int, int>(3, 300));
	m2.insert(pair<int, int>(2, 200));
	m2.insert(pair<int, int>(4, 400));

	cout << "-----交换前-----" << endl;
	
	printMap(m1);
	printMap(m2);

	m1.swap(m2);

	cout << "-----交换后-----" << endl;

	printMap(m1);
	printMap(m2);

}

int main()
{
	test01();

	test02();
}

m不为空
m size = 4
-----交换前-----
key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

key = 1 value = 100
key = 2 value = 200
key = 3 value = 300
key = 4 value = 400

-----交换后-----
key = 1 value = 100
key = 2 value = 200
key = 3 value = 300
key = 4 value = 400

key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

插入和删除

image.png

#include<iostream>
#include<map>

using namespace std;

void printMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
	cout << endl;
}


void test01()
{
	map<int, int> m;

	//插入, 使用insert来插入
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 30));
	m.insert(make_pair(2, 20));
	m.insert(pair<int, int>(4, 40));

	printMap(m);

	//访问,可以通过key来访问
	cout << "key = 2, value = " << m[2] << endl;
	cout << endl;

	//删除
	m.erase(m.begin());

	printMap(m);

	m.erase(3);  //按照key=3删除

	printMap(m);

	//清空
	//m.erase(m.begin(), m.end());
	m.clear();
	printMap(m);

}


int main()
{
	test01();
}

key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

key = 2, value = 20

key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

key = 2 value = 20
key = 4 value = 40

查找和统计

image.png

#include<iostream>
#include<map>

using namespace std;

void printMap(map<int, int>& m)
{
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
	cout << endl;
}


void test01()
{
	map<int, int> m;

	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 30));
	m.insert(make_pair(2, 20));
	m.insert(pair<int, int>(4, 40));

	printMap(m);

	map<int, int>::iterator it = m.find(3);  //查找key=3的迭代器

	if (it != m.end())
	{
		cout << "找到了元素, key = " << (*it).first << " value = " << (*it).second << endl;
	}
	else
	{
		cout << "找不到元素" << endl;
	}

	//map不允许重复元素,因此count结果非1即0
	int num = m.count(3);
	cout << "num = " << num << endl;
}


int main()
{
	test01();
}

key = 1 value = 10
key = 2 value = 20
key = 3 value = 30
key = 4 value = 40

找到了元素, key = 3 value = 30
num = 1

排序

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

内置数据类型
#include<iostream>
#include<map>

using namespace std;

class myCompare
{
public:
	bool operator()(int v1, int v2) const
	{
		return v1 > v2;
	}
};

void printMap(map<int, int, myCompare>& m)
{
	for (map<int, int, myCompare>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << (*it).first << " value = " << (*it).second << endl;
	}
	cout << endl;
}


void test01()
{
	//自定义排序规则, 降序
	map<int, int, myCompare> m;

	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 30));
	m.insert(make_pair(2, 20));
	m.insert(pair<int, int>(4, 40));

	printMap(m);

}


int main()
{
	test01();
}

key = 4 value = 40
key = 3 value = 30
key = 2 value = 20
key = 1 value = 10
自定义数据类型

注1:对于自定义数据类型,必须给定排序规则,否则map容器不知道如何自动排序,与set容器一样
注2:编写仿函数时,比较的两个对象是key,而非value,且记得在函数后面加const

#include<iostream>
#include<map>

using namespace std;

class Person
{
public:
	Person(string name)
	{
		this->m_Name = name;
	}

	string m_Name;
};

//按照姓名英文字母进行排序,注意比较的是两个key值
class myCompare
{
public:
	bool operator()(const Person& p1, const Person& p2) const
	{
		return p1.m_Name < p2.m_Name;
	}
};

void printMap(const map<Person, int, myCompare>& m)
{
	for (map<Person, int, myCompare>::const_iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "Name = " << it->first.m_Name << " Age = " << it->second << endl;
	}
}


void test01()
{
	Person p1("Tom");
	Person p2("Mike");
	Person p3("Amy");
	Person p4("Bob");

	map<Person, int, myCompare> m;

	m.insert(make_pair(p1, 18));
	m.insert(make_pair(p2, 30));
	m.insert(make_pair(p3, 25));
	m.insert(pair<Person, int>(p4, 28));

	printMap(m);


}

int main()
{
	test01();
}

Name = Amy Age = 25
Name = Bob Age = 28
Name = Mike Age = 30
Name = Tom Age = 18
#include<iostream>
#include<vector>
#include<map>
#include<ctime>

using namespace std;

class Person
{
public:
	Person(string name, int salary)
	{
		m_Name = name;
		m_salary = salary;
	}
	string m_Name;
	int m_salary;
};

void distribute(multimap <int, Person>& m, vector<Person> &v1, vector<int> &v2)
{
	for (vector<Person>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		int depart = rand() % v2.size();
		m.insert(make_pair(v2[depart], (*it)));
	}
}

void printMap(multimap<int, Person>& m)
{
	for (int i = 0; i < 3; i++)
	{
		cout << "-----" << i << "-----" << endl;
		multimap<int, Person>::iterator pos = m.find(i);
		int count = m.count(i);
		int index = 0;
		for (; pos != m.end() && index < count; pos++, index++)
		{
			cout << "Name = " << (*pos).second.m_Name << " " << " Salary = " << (*pos).second.m_salary << endl;
		}
		cout << endl;
	}
	
}


int main()
{
	srand((unsigned int)time(NULL));

	//创建multimap,存储键值对
	multimap<int, Person> m;

	//创建员工
	vector<Person> v1;

	Person p1("A", 1000);
	Person p2("B", 1500);
	Person p3("C", 1200);
	Person p4("D", 1100);
	Person p5("E", 1800);
	Person p6("F", 1600);
	Person p7("G", 1900);
	Person p8("H", 1300);
	Person p9("I", 1400);
	Person p10("J", 1700);

	v1.push_back(p1);
	v1.push_back(p2);
	v1.push_back(p3);
	v1.push_back(p4);
	v1.push_back(p5);
	v1.push_back(p6);
	v1.push_back(p7);
	v1.push_back(p8);
	v1.push_back(p9);
	v1.push_back(p10);

	//创建部门,0为策划,1为美术,2为研发
	vector<int> v2;

	v2.push_back(0);
	v2.push_back(1);
	v2.push_back(2);

	//分配部门
	distribute(m, v1, v2);

	//打印结果
	printMap(m);

}

-----0-----
Name = B  Salary = 1500
Name = H  Salary = 1300

-----1-----
Name = A  Salary = 1000
Name = C  Salary = 1200
Name = E  Salary = 1800

-----2-----
Name = D  Salary = 1100
Name = F  Salary = 1600
Name = G  Salary = 1900
Name = I  Salary = 1400
Name = J  Salary = 1700

函数对象

概念

  • 重载函数调用操作符的类,其对象称为函数对象
  • 函数对象使用重载的()时,行为类似函数调用,也叫仿函数
  • 函数对象(仿函数)是一个类,不是一个函数
#include<iostream>

using namespace std;

//函数对象可以像普通函数一样传参调用
class myAdd
{
public:
	//仿函数
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};

void test01()
{
	myAdd myadd;
	cout << myadd(10, 10) << endl;
}

//函数对象可以有自己的状态
class myPrint
{
public:
	myPrint()
	{
		this->count = 0;
	}
	void operator()(string s)
	{
		cout << s << endl;
		this->count += 1;
	}

	int count; //内部状态
};

void test02()
{
	myPrint myprint;
	myprint("Hello!");
	myprint("Hello!");
	myprint("Hello!");

	cout << myprint.count << endl;
}

//函数对象可以作为参数传递

void doPrint(myPrint &m, string s)
{
	m(s);
}

void test03()
{
	myPrint myprint;
	doPrint(myprint, "Hello C++");
}

int main()
{
	test01();

	test02();

	test03();
}

20
Hello!
Hello!
Hello!
3
Hello C++

谓词

概念

  • 返回bool类型的仿函数称为谓词
  • 若operator()接收一个参数,则称之为一元谓词
  • 若operator()接收两个参数,则称之为二元谓词

一元谓词

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

using namespace std;

//定义类,功能为判断是否值大于5
//一元谓词
class upFive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};

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

	//upFive() 匿名函数对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), upFive());
	if (it == v.end())
	{
		cout << "找不到" << endl;
	}
	else
	{
		cout << "找到了大于5的数字: " << *it << endl;
	}
}

int main()
{
	test01();
}

找到了大于5的数字: 6

二元谓词

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

using namespace std;

//二元谓词
class myCompare
{
public:
	bool operator()(int val1, int val2)
	{
		//降序
		return val1 > val2;
	}
};

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

	//默认升序
	sort(v.begin(), v.end());

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

	//使用函数对象,改为降序
	//注意使用时需要加()
	sort(v.begin(), v.end(), myCompare());

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

}

int main()
{
	test01();
}

10 20 30 40 50
50 40 30 20 10

内建函数对象

引入头文件#include<functional>

算术仿函数

image.png

#include<iostream>
#include<functional>

using namespace std;

//negate 一元仿函数 取反
void test01()
{
	negate<int> n;

	cout << n(50) << endl;
}

//plus 二元仿函数  加法
void test02()
{
	plus<int> p;
	cout << p(10, 20) << endl;
}

int main()
{
	test01();

	test02();
}

-50
30

关系仿函数

image.png

#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>

using namespace std;

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

//大于 greater
void test01()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(20);
	v.push_back(30);
	v.push_back(50);

	printVector(v);

	//自定义降序
	//sort(v.begin(), v.end(), myConpare());
	sort(v.begin(), v.end(), greater<int>());

	printVector(v);

}

int main()
{
	test01();
}

10 40 20 30 50
50 40 30 20 10

逻辑仿函数

image.png

#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>

using namespace std;

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

//逻辑仿函数
void test01()
{
	vector<bool> v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(true);
	v.push_back(false);

	printVector(v);

	vector<bool> v2;
	v2.resize(v.size());

	transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());

	printVector(v2);

}

int main()
{
	test01();
}

1 0 1 0
0 1 0 1

STL-常用算法

image.png

遍历算法

for_each

遍历容器
image.png

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

using namespace std;

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

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

class myPrint2
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	printvector(v);

	//普通函数传入
	for_each(v.begin(), v.end(), myPrint);
	cout << endl;

	//函数对象传入,注意有括号
	for_each(v.begin(), v.end(), myPrint2());
	cout << endl;
}

int main()
{
	test01();
}

10 40 20 30 50
10 40 20 30 50
10 40 20 30 50

transform

image.png

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

using namespace std;

//void printvector(vector<int>& v)
//{
//	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
//	{
//		cout << *it << " ";
//	}
//	cout << endl;
//}
//
//void myPrint(int val)
//{
//	cout << val << " ";
//}
//
class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

class Transform
{
public:
	int operator()(int val)
	{
		return val;
	}
};

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

	vector<int> v2;
	//注意目标容器,需要提前开辟空间
	v2.resize(v.size());

	transform(v.begin(), v.end(), v2.begin(), Transform());

	for_each(v2.begin(), v2.end(), myPrint());

}

int main()
{
	test01();
}

10 40 20 30 50

查找算法

find

image.png
注:对于自定义数据类型,需要在自定义类里面,重载运算符==号,以便于自定义类型的比较

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

using namespace std;

//查找内置数据类型
void test01()
{
	vector<int> v;
	//for (int i = 0; i < 10; i++)
	//{
	//	v.push_back(i);
	//}
	v.push_back(10);
	v.push_back(15);

	//查找元素
	vector<int>::iterator it = find(v.begin(), v.end(), 15);
	if (it == v.end())
	{
		cout << "Not found!" << endl;
	}
	else
	{
		//it为指定位置迭代器, *it为该位置的元素值
		cout << "Found: " << *it << endl;
	}
}

//查找自定义数据类型
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	//需要重载==以让find函数知道如何比较Person数据类型
	bool operator==(const Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	string m_Name;
	int m_Age;
};

void test02()
{
	vector<Person> v;

	//创建数据
	Person p1("Tom", 16);
	Person p2("Jack", 25);
	Person p3("Amy", 28);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);

	vector<Person>::iterator it = find(v.begin(), v.end(), p2);
	if (it == v.end())
	{
		cout << "Not found!" << endl;
	}
	else
	{
		cout << "Found: Name is " << (*it).m_Name << " Age is " << (*it).m_Age << endl;
	}

}

int main()
{
	test01();

	test02();
}

Found: 15
Found: Name is Jack Age is 25

find_if

image.png
注:注意使用函数对象来作为_Pred

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

using namespace std;

//查找内置数据类型
class upFive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};


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

	//查找大于5的元素
	vector<int>::iterator it = find_if(v.begin(), v.end(), upFive());
	if (it == v.end())
	{
		cout << "Not found!" << endl;
	}
	else
	{
		//it为指定位置迭代器, *it为该位置的元素值
		cout << "Found: " << *it << endl;
	}
}

//查找自定义数据类型
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	//需要重载==以让find函数知道如何比较Person数据类型
	bool operator==(const Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	string m_Name;
	int m_Age;
};

class upTwenty
{
public:
	bool operator()(const Person& p)
	{
		return p.m_Age > 25;
	}
};


void test02()
{
	vector<Person> v;

	//创建数据
	Person p1("Tom", 16);
	Person p2("Jack", 25);
	Person p3("Amy", 28);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);

	//查找年龄大于20的人
	vector<Person>::iterator it = find_if(v.begin(), v.end(), upTwenty());
	if (it == v.end())
	{
		cout << "Not found!" << endl;
	}
	else
	{
		cout << "Found: Name is " << (*it).m_Name << " Age is " << (*it).m_Age << endl;
	}

}

int main()
{
	test01();

	test02();
}

Found: 6
Found: Name is Amy Age is 28

adjacent_find

image.png
注:注意这两个关键词:相邻重复

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

using namespace std;

void test01()
{
	vector<int> v;
	v.push_back(0);
	v.push_back(2);
	v.push_back(0);
	v.push_back(2);
	v.push_back(3);
	v.push_back(3);
	v.push_back(4);

	vector<int>::iterator it = adjacent_find(v.begin(), v.end());
	if (it == v.end())
	{
		cout << "Not found!" << endl;
	}
	else
	{
		cout << "Found: " << *it << endl;
	}
}


int main()
{
	test01();
}

Found: 3

binary_search

image.png
注1:该算法适用于有序序列
注2:返回值为bool类型

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

using namespace std;

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

	bool ret = binary_search(v.begin(), v.end(), 5);
	if(ret)
	{
		cout << "Found!" << endl;
	}
	else
	{
		cout << "Not found!" << endl;
	}
}


int main()
{
	test01();
}

Found!

count

image.png
注:对于自定义数据类型,需要在自定义类里面,重载运算符==号,以便于自定义类型的比较

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

using namespace std;

//统计内置数据类型
void test01()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(10);
	v.push_back(20);
	v.push_back(20);
	v.push_back(10);
	v.push_back(20);
	v.push_back(20);
	v.push_back(20);

	int num = count(v.begin(), v.end(), 20);

	cout << "num of 20 is " << num << endl;
}

//统计自定义数据类型
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	bool operator==(const Person& p)
	{
		if (this->m_Age == p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	string m_Name;
	int m_Age;
};


void test02()
{
	vector<Person> v;

	//创建数据
	Person p1("Tom", 16);
	Person p2("Jack", 25);
	Person p3("Amy", 28);
	Person p4("Tony", 16);
	Person p5("Lucy", 16);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);

	Person p("Mike", 16);

	//统计与Mike同岁数的人数
	int num = count(v.begin(), v.end(), p);

	cout << "num of age equal p is " << num << endl;
}

int main()
{
	test01();

	test02();
}


num of 20 is 5
num of age equal p is 3

count_if

image.png

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

using namespace std;

//统计内置数据类型
class upFive
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};


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

	//统计大于5的个数
	int num = count_if(v.begin(), v.end(), upFive());

	cout << "num of >5 is " << num << endl;
}

//统计自定义数据类型
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	bool operator==(const Person& p)
	{
		if (this->m_Age == p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	string m_Name;
	int m_Age;
};

class upTwentyFive
{
public:
	bool operator()(const Person &p)
	{
		return p.m_Age > 25;
	}
};


void test02()
{
	vector<Person> v;

	//创建数据
	Person p1("Tom", 16);
	Person p4("Tony", 20);
	Person p2("Jack", 25);
	Person p3("Amy", 28);
	Person p5("Lucy", 30);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);


	//统计年龄大于25岁的人数个数
	int num = count_if(v.begin(), v.end(), upTwentyFive());

	cout << "num of age > 25 is " << num << endl;
}

int main()
{
	test01();

	test02();
}

num of >5 is 4
num of age > 25 is 2

排序算法

sort

image.png

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	//sort排序,默认升序
	sort(v.begin(), v.end());
	
	//擅用STL库来实现输出
	for_each(v.begin(), v.end(), Myprint());
	cout << endl;

	//sort改变为降序
	sort(v.begin(), v.end(), greater<int>());

	for_each(v.begin(), v.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

10 20 30 40 50
50 40 30 20 10

random_shuffle

image.png

#include<iostream>
#include<vector>
#include<algorithm>
#include<ctime>

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

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

	for_each(v.begin(), v.end(), Myprint());
	cout << endl;

	//打乱顺序
	random_shuffle(v.begin(), v.end());

	for_each(v.begin(), v.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

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

merge

image.png
注:两个容器必须有序,且都是升序/降序

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	cout << "v2: ";
	for_each(v2.begin(), v2.end(), Myprint());
	cout << endl;

	//目标容器,注意提前开辟内存空间
	vector<int> v3;
	v3.resize(v1.size() + v2.size());

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

	cout << "v3: ";
	for_each(v3.begin(), v3.end(), Myprint());
	cout << endl;
}

int main()
{
	test01();
}

v1: 0 1 2 3 4 5 6 7 8 9
v2: 1 2 3 4 5 6 7 8 9 10
v3: 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10

reverse

image.png

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	reverse(v1.begin(), v1.end());

	cout << "v1(reverse): ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

v1: 0 1 2 3 4 5 6 7 8 9
v1(reverse): 9 8 7 6 5 4 3 2 1 0

拷贝和替换算法

copy

image.png

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

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

	copy(v1.begin(), v1.end(), v2.begin());

	cout << "v2: ";
	for_each(v2.begin(), v2.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

v2: 0 1 2 3 4 5 6 7 8 9

replace

image.png

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	//将所有的2替换为20
	replace(v1.begin(), v1.end(), 2, 20);

	cout << "v1(replaced): ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

v1: 0 1 2 3 4 5 6 7 8 9
v1(replaced): 0 1 20 3 4 5 6 7 8 9

replace_if

image.png

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

class Myreplace
{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};

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

	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	//将大于5的数字,都替换为10
	replace_if(v1.begin(), v1.end(), Myreplace(), 10);

	cout << "v1(replaced): ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

v1: 0 1 2 3 4 5 6 7 8 9
v1(replaced): 0 1 2 3 4 5 10 10 10 10

swap

image.png

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

using namespace std;

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	cout << "交换前" << endl;
	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	cout << "v2: ";
	for_each(v2.begin(), v2.end(), Myprint());
	cout << endl;

	swap(v1, v2);


	cout << "交换后" << endl;
	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	cout << "v2: ";
	for_each(v2.begin(), v2.end(), Myprint());
	cout << endl;

}

int main()
{
	test01();
}

交换前
v1: 0 1 2 3 4 5 6 7 8 9
v2: 10 11 12 13 14 15 16 17 18 19
交换后
v1: 10 11 12 13 14 15 16 17 18 19
v2: 0 1 2 3 4 5 6 7 8 9

算术生成算法

注意是导入库#include<numeric>

accumulate

image.png

#include<iostream>
#include<vector>
#include<numeric>

using namespace std;

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

	int total = accumulate(v1.begin(), v1.end(), 0);

	cout << "total = " << total << endl;

}

int main()
{
	test01();
}

5050

fill

image.png

#include<iostream>
#include<vector>
#include<numeric>
#include<algorithm>

using namespace std;

class Mypint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{
	vector<int> v1;
	v1.resize(10);

	fill(v1.begin()+1, v1.end(), 100);

	for_each(v1.begin()+1, v1.end(), Mypint());
	cout << endl;

}

int main()
{
	test01();
}

100 100 100 100 100 100 100 100 100

集合算法

set_intersection

image.png
注1:求交集的两个集合必须都是有序序列
注2:目标容器开辟空间,需要从两个集合中取最小值
注3:返回值为交集中最后一个元素的迭代器位置

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

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	vector<int> v3;
	v3.resize(min(v1.size(), v2.size()));

	vector<int>::iterator it = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());

	//注意这里使用it而非v3.end(), 因为v3.end()会把v3的开辟空间内的所有元素打印(其他元素为0)
	for_each(v3.begin(), it, Myprint());
	cout << endl;
	for_each(v3.begin(), v3.end(), Myprint());

}

int main()
{
	test01();
}

5 6 7 8 9
5 6 7 8 9 0 0 0 0 0

set_union

image.png
注1:目标容器开辟空间,需要将两个集合的size相加

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

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

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

	vector<int>::iterator it = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());

	for_each(v3.begin(), it, Myprint());
	cout << endl;

}

int main()
{
	test01();
}

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

set_difference

image.png

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

class Myprint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

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

	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Myprint());
	cout << endl;

	cout << "v2: ";
	for_each(v2.begin(), v2.end(), Myprint());
	cout << endl;

	vector<int> v3;
	v3.resize(max(v1.size(), v2.size()));

	vector<int>::iterator it = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());

	cout << "v1-v2: ";
	for_each(v3.begin(), it, Myprint());
	cout << endl;

	it = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v3.begin());

	cout << "v2-v1: ";
	for_each(v3.begin(), it, Myprint());
	cout << endl;


}

int main()
{
	test01();
}

v1: 0 1 2 3 4 5 6 7 8 9
v2: 5 6 7 8 9 10 11 12 13 14
v1-v2: 0 1 2 3 4
v2-v1: 10 11 12 13 14

参考链接

黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难(P167-P263)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值