目录
1.模板
1.1模板的概念
1.2函数模板
1.2.1函数模板语法
1.2.2函数模板注意事项
1.2.3函数模板案例
1.2.4普通函数与函数模板的区别
1.2.5普通函数与函数模板调用规则
1.2.6 模板的局限性
1.3类模板
1.3.1类模板语法
1.3.2类模板与函数模板区别
1.3.3类模板中成员函数创建时机
1.3.4类模板对象做函数参数
1.3.5类模板与继承
1.3.6类模板成员函数的类外实现
1.3.7类模板份文件编写
1.3.8类模板与友元
1.3.9类模板案例
2.STL初识
2.1STL诞生
2.2STL基本概念
2.3STL六大组件
2.4STL中容器、算法、迭代器
2.5容器算法迭代器初识
2.5.1vector存放内置数据类型
2.5.2vector存放自定义数据类型
2.5.3vector容器嵌套容器
3.STL—常用容器
3.1string容器
3.1.1string基本概念
3.1.2string构造函数
3.1.3string赋值操作
3.1.4string字符串拼接
3.1.5string查找和替换
3.1.6string字符串比较
3.1.7string字符提取
3.1.8string插入和删除
3.1.9string子串
3.2vector容器
3.2.1vector基本概念
3.2.2vector构造函数
3.2.3vector赋值操作
3.2.4vector容量和大小
3.2.5vector插入和删除
3.2.6vector数据存取
3.2.7vector互换容器
3.2.8vector预留空间
3.3deque容器
3.3.1deque容器基本概念
3.2.2deque构造函数
3.3.3deque赋值操作
3.3.4deque大小操作
3.3.5deque插入和删除
3.3.6deque数据存取
3.3.7deque排序
3.4案例——评委打分
3.4.1案例描述
3.4.2实现步骤
3.5stack容器
3.5.1stack基本概念
3.5.2stack容器常用接口
3.6queue容器
3.6.1queue基本概念
3.6.2queue常用接口
3.7list容器
3.7.1list基本概念
3.7.2list构造函数
3.7.3list赋值和交换
3.7.3list大小操作
3.7.5list插入和删除
3.7.6list数据存取
3.7.7list反转和排序
3.7.8排序案例
3.8set/multiset容器
3.8.1set概念
3.8.2set的构造和赋值
3.8.3set大小和交换
3.8.4set插入和删除
3.8.5set查找和统计
3.8.6set和multiset区别
3.8.7pair队组创建
3.8.8set容器排序
3.9map/multimap容器
3.9.1map基本概念
3.9.2map构造和赋值
3.9.3map大小和交换
3.9.4map容器-插入和删除
3.9.5map查找和统计
3.9.6map容器排序
3.10案例-员工分组
3.10.1案例描述
4 STL函数对象
4.1函数对象
4.1.1函数对象概念
4.1.2函数对象使用
4.2谓词
4.2.1谓词概念
4.2.2一元谓词
4.2.3二元谓词
4.3内建函数对象
4.3.1内建函数对象意义
4.3.2算数仿函数
4.3.3关系仿函数
4.3.4逻辑仿函数
5STL—常用算法
5.1常用遍历算法
5.1.1for_each
5.1.2transform
5.2常用查找算法
5.2.1find
5.2.2find_if
5.2.3adjacent_find
5.2.4binary_search
5.2.5count
5.2.6count_if
5.3常用排序算法
5.3.1sort
5.3.2random_shuffle
5.3.3merge
5.3.4reverse
5.4常用拷贝和替换算法
5.4.1copy
5.4.2replace
5.4.3replace_if
5.4.4swap
5.5常用算术生成算法
5.5.1accumulate
5.5.2fill
5.6常用集合算法
5.6.1set_intersection
5.6.2set_union
5.6.3set_difference
模板就是建立通用的模具,大大提高编程的复用性
函数模板作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template
解释:
template——声明创建模板
typename——表明其后面的符号是一种数据类型,可以用class代替
T——通用数据类型,名称可以替换,通常为大写字母
#include
using namespace std;
//函数模板
//两个整形交换的函数
void SwapInt(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
//交换两个浮点型函数
void SwapDouble(double &a, double &b)
{
double temp = a;
a = b;
b = temp;
}
//函数模板
template//声明一个模板,告诉编译器后面板代码中紧跟的T不要报错,T是一个通用数据类型
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 10;
int b = 20;
SwapInt(a, b);
cout << "a = " << a << ",b = " << b << endl;
double c = 1.1;
double d= 2.2;
SwapDouble(c, d);
cout << "c = " << c << ",d = " << d << endl;
//利用函数模板交换
//两种方式使用函数模板
//1.自动类型推导
mySwap(a, b);
mySwap(c, d);
cout << "a = " << a << ",b = " << b << endl;
cout << "c = " << c << ",d = " << d << endl;
///2.显式指定类型
mySwap(a, b);
cout << "a = " << a << ",b = " << b << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
注意事项:
#include
using namespace std;
//函数模板注意事项
template //typename可以替换成class
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
//1.自动类型推导,必须推导出一定的数据类型T才可以使用
void test01()
{
int a = 10;
int b = 20;
mySwap(a, b); //正确
cout << "a = " << a << ",b = " << b << endl;
char c = 'c';
//mySwap(a, c); //错误,推导不出一致的T类型
}
//2.模板必须要确定出T的数据类型,才可以使用
template
void func()
{
cout << "func()调用" << endl;
}
void test02()
{
//func(); //错误❌
func(); //可以!
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:
使用模板时,必须确定出通用数据类型T,并且能够推导出一致的类型。
案例描述:
#include
using namespace std;
//实现通用 对数组进行排序的函数
//规则 从大到小
//算法 选择排序
//测试 char数组 int数组
//排序算法
//交换函数模板
template
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
//排序函数模板
template
void mySort(T arr[],int len)
{
for (int i = 0; i < len; i++)
{
int max = i;//认定最大值下标
for (int j = i + 1; j < len; j++)
{
//认定的最大值比遍历出的数值要小,说明下标的元素才是真正的最大值
if (arr[max] < arr[j])
{
max = j;
}
}
if (max != i)
{
//交换max和i下标的元素
mySwap(arr[max], arr[i]);
}
}
}
//打印数组模板
template
void printArray(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
void test01()
{
//测试char数组
char charArr[] = "badcfe";
int num = sizeof(charArr) / sizeof(char);
mySort(charArr, num);
printArray(charArr, num);
}
void test02()
{
//测试int数组
int intArr[] = { 7,8,5,2,3,4,1 };
int num = sizeof(intArr) / sizeof(int);
mySort(intArr, num);
printArray(intArr, num);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
普通函数与模板函数的区别:
#include
using namespace std;
//普通函数与模板函数区别
//1.普通函数调用可以发生隐式类型转换
//2.函数模板 用自动类型推导,不可以发生隐式类型转换
//3.函数模板 用显示指定类型,可以发生隐式类型转换
//普通函数
int myAdd(int a, int b)
{
return a + b;
}
//函数模板
template
T myAdd02(T a,T b)
{
return a + b;
}
void test01()
{
int a = 10;
int b = 20;
char c = 'c';
cout << myAdd(a, b) << endl;
cout << myAdd(a, c) << endl; //c隐式转换为int类型
//自动类型推导
cout << myAdd02(a, b) << endl;
//cout << myAdd02(a, c) << endl; //报错, 用自动类型推导,不可以发生隐式类型转换
cout << myAdd02(a, c) << endl;//用显示指定类型,可以发生隐式类型转换
}
int main()
{
test01();
system("pause");
return 0;
}
调用规则如下:
#include
using namespace std;
//普通函数与函数模板调用规则
//1.如果函数模板和普通模板都可以实现,优先调用普通函数
//2.可以通过空模板参数列表来强制调用函数模板
//3.函数模板也可以发生重载
//4.如果函数模板可以产生更好的匹配,优先调用函数模板
void myPrint(int a, int b)
{
cout << "调用的是普通函数!" << endl;
}
template
void myPrint(T a, T b)
{
cout << "调用的模板!" << endl;
}
template
void myPrint(T a,T b,T c)
{
cout << "重载的模板!" << endl;
}
void test01()
{
int a = 10;
int b = 20;
myPrint(10, 20); //调用的时普通函数
myPrint<>(a,b); //通过空模板参数列表来强制调用函数模板
myPrint<>(a, b,100); //函数模板也可以发生重载
char c1 = 'a';
char c2 = 'b';
myPrint(c1, c2); //如果函数模板可以产生更好的匹配,优先调用函数模板
}
int main()
{
test01();
system("pause");
return 0;
}
总结:既然提供了函数模板,最好不要提供普通函数,否则容易出现二义性
局限性:模板的通用性并不是万能的
例如:
template
void f(T a, T b)
{
a = b;
}
在上述代码中提供的赋值操作,如果传入的a和b是一个数组,就无法实现了。
再例如:
template
void f(T a, T b)
{
if(a > b)
{...... }
}
在上述代码中,如果T的数据类型是像Person这样的自定义数据类型,也无法正常运行。
因此C++为了解决这种问题,提供了模板的重载,可以为这些特定的类型提供具体化的模板。
#include
#include
using namespace std;
//模板局限性
//模板并不是万能的有些特定数据类型,需要用具体化方式做特殊实现
class Person
{
public:
Person(string name, int age)
{
m_age = age;
m_name = name;
}
string m_name;
int m_age;
};
//对比两个数是否相等
//普通函数模板
template
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_name == p2.m_name) && (p1.m_age == p2.m_age))
return true;
else
return false;
}
void test01()
{
int a = 10;
int b = 20;
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();
system("pause");
return 0;
}
总结:
类模板作用:建立一个通用类,类中的成员、数据类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template、
类
解释:
template——声明创建模板
typename——表明其后面的符号是一种数据类型,可以用class代替
T——通用的数据类型,名称可以替换,通常为大写字母
示例:
#include
#include
using namespace std;
//类模板
template
class Person
{
public:
Person(NameType name, AgeType age)
{
m_age = age;
m_name = name;
}
void showPerson()
{
cout <<"Name: "<< this->m_name << "\tAge: " < m_age << endl;
}
public:
NameType m_name;
AgeType m_age;
};
void test01()
{
//指定NameType为string类型,AgeType为int类型
Person p1("孙悟空", 999);
p1.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
总结:类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板。
类模板与函数模板区别主要有两点:
#include
using namespace std;
//类模板与函数模板区别
template
class Person
{
public:
Person(NameType name, AgeType age)
{
m_Name = name;
m_Age = age;
}
void showPerson()
{
cout << "Name: " << m_Name << "\tAge: " << m_Age << endl;
}
NameType m_Name;
AgeType m_Age;
};
//1.类模板没有自动类型推导的使用方式
void test01()
{
//Person p("孙悟空", 1000);错误❌,无法用自动类型推导
Person p("孙悟空", 1000);//正确,只能用显式指定类型
p.showPerson();
}
//2.类模板在模板参数列表中可以有默认参数
void test02()
{
Person p("猪八戒", 999);
p.showPerson();
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:
类模板中成员函数与普通类中成员函数创建时机是有区别的:
#include
using namespace std;
//类模板中成员函数创建时机
//类模板中成员函数在调用时才创建
class Person1
{
public:
//类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成
void showPerson1()
{
cout << "Person1 show" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "Person2 show" << endl;
}
};
template
class MyClass
{
public:
T obj;
//类模板中成员函数
void func1()
{
obj.showPerson1();
}
void func2()
{
obj.showPerson2();
}
};
void test01()
{
MyClass m;
m.func1();
//m.func2(); //编译会出错,说明函数调用才会创建成员函数
MyClass n;
n.func2();
}
int main()
{
test01();
system("pause");
return 0;
}
总结:类模板中成员函数并不是一开始就创建,而是在调用时才创建。
一共有三种传入方式:
#include
using namespace std;
//类模板对象做函数参数
template
class Person
{
public:
Person(T1 name, T2 age)
{
m_age = age;
m_name = name;
}
void showPerson()
{
cout << "Name: " << m_name << "\tAge: " << m_age << endl;
}
T1 m_name;
T2 m_age;
};
//1.指定传入类型——直接显示对象的数据类型
void printPerson1(Person& p)
{
p.showPerson();
}
void test01()
{
Person p("孙悟空", 100);
printPerson1(p);
}
//2.参数模板化——将对象中的参数变为模板进行传递
template
void printPerson2(Person& p)
{
p.showPerson();
cout << "T1的类型为:" << typeid(T1).name() << endl;
cout << "T2的类型为:" << typeid(T2).name() << endl;
}
void test02()
{
Person p("猪八戒", 100);
printPerson2(p);
}
//3.整个类模板化——将这个对象类型 模板化进行传递
template
void printPerson3(T & p)
{
p.showPerson();
cout << "T的类型为:" << typeid(T).name() << endl;
}
void test03()
{
Personp("唐僧", 30);
printPerson3(p);
}
int main()
{
test01();
test02();
test03();
system("pause");
return 0;
}
总结:
当类模板碰到继承时,需要注意以下几点:
#include
using namespace std;
//类模板与继承
template
class Base
{
T m;
};
//class Son:public Base //错误❌,必须要知道父类中的T类型,才能继承给子类
class Son:public Base
{
};
void test01()
{
Son s1;
}
//如果想灵活指定父类中T的类型,子类也需要变类模板
template
class Son2 :public Base
{
public:
Son2()
{
cout << "T1的类型为: " << typeid(T1).name() << endl;
cout << "T2的类型为: " << typeid(T2).name() << endl;
}
T1 obj;
};
void test02()
{
Son2 S2;
}
int main()
{
test02();
system("pause");
return 0;
}
#include
using namespace std;
//类模板成员函数类外实现
template
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
//构造函数类外实现
template
Person::Person(T1 name, T2 age)
{
m_Name = name;
m_Age = age;
}
//成员函数类外实现
template
void Person::showPerson()
{
cout << "Name: " << m_Name << "\tAge: " << m_Age << endl;
}
void test01()
{
Personp("Tom", 20);
p.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
总结:类模板中成员函数类外实现时,需要加上模板参数列表
问题:
解决:
person.hpp中代码
#pragma once
#include
using namespace std;
//类模板文件编写问题以及解决方式
template
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
template
Person::Person(T1 name, T2 age)
{
m_Age = age;
m_Name = name;
}
template
void Person::showPerson()
{
cout << "Name: " << m_Name << "\tAge: " << m_Age << endl;
}
#include
//第一种解决方式,直接包含源文件
//#include "person.cpp"
//第二种解决方式,将.h和.cpp中内容写在一起,将后缀名改为.hpp文件
#include "person.hpp"
using namespace std;
void test01()
{
Personp("Jerry", 18);
p.showPerson();
}
int main()
{
test01();
system("pause");
return 0;
}
总结:主流的解决方式是第二种,将类模板成员函数写到一起,并将后缀名改为.hpp
学习目标:
掌握类模板配合友元函数的类内实现和类外实现
#include
using namespace std;
//通过全局函数打印Person信息
//提前让编译器知道Person类的存在
template
class Person;
//类外实现
template
void printPerson2(Person p)
{
cout << "类外实现——Name: " << p.m_name << "\tAge: " << p.m_age << endl;
}
template
class Person
{
//全局函数类内是实现
friend void printPerson(Person p)
{
cout << "类内实现——Name: " << p.m_name << "\tAge: " <(Person p);
public:
Person(T1 name, T2 age)
{
m_name = name;
m_age = age;
}
private:
T1 m_name;
T2 m_age;
};
//1.全局函数在类内实现
void test01()
{
Person p("Tom", 20);
printPerson(p);
}
//2.全局函数在类外实现
void test02()
{
Person p("Jerry", 30);
printPerson2(p);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:建议全局函数做类内实现,用法简单,而且编译器可以直接识别。
案例描述:实现一个通用数组类,要求如下:
示例:
myArray16.hpp代码如下:
#pragma once
#include
using namespace std;
template
class MyArray
{
public:
//有参构造 参数 容量
MyArray(int Capacity)
{
m_Capacity = Capacity;
m_Size = 0;
pAddress = new T[Capacity];
}
//拷贝构造
MyArray(const MyArray& arr)
{
pAddress = new T[arr.m_Capacity];
this->m_Capacity = arr.m_Capacity;
this->m_Size = arr.m_Size;
for (int i = 0; i < m_Size; i++)
{
pAddress[i] = arr.pAddress[i];
}
}
//operator= 防止浅拷贝问题 a = b = c
MyArray& operator=(const MyArray& arr)
{
//先判断原来堆区是否有数据,如果有先释放
if (this->pAddress != NULL)
{
delete[]this->pAddress;
this->pAddress = NULL;
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_Capacity == this->m_Size)
{
return;
}
this->pAddress[this->m_Size] = val; //在数组末尾插入数据
this->m_Size++; //更新数组大小
}
//尾删法
void Pop_Back()
{
//让用户访问不到最后一个元素,即为尾删
if (this->m_Size == 0)
{
return;
}
this->m_Size--;
}
//通过下标方式访问数组元素 arr[0] = 100
T& operator[](int index) //如果要返回可以作为左值存在,则返回引用
{
return this->pAddress[index];
}
//返回数组容量
int getCapacity()
{
return this->m_Capacity;
}
//返回数组大小
int getSize()
{
return this->m_Size;
}
//析构函数
~MyArray()
{
if (pAddress != NULL)
{
delete[] pAddress;
pAddress = NULL;
}
}
private:
T* pAddress; //指针指向堆区开辟的真实数组
int m_Capacity; //数组容量
int m_Size; //数组大小
};
测试代码:
#include
using namespace std;
#include "myArray16.hpp"
void printIntArray(MyArray & arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << arr[i] << endl;
}
}
void test01()
{
MyArray arr1(5);
for (int i = 0; i < 5; i++)
{
arr1.Push_Back(i); //利用尾插法向数组中插入数据
}
cout << "arr1的打印输出为:" << endl;
printIntArray(arr1);
cout << "arr1的容量为:" < arr2(arr1);
cout << "arr2的打印输出为:" << endl;
printIntArray(arr2);
//尾删
arr2.Pop_Back();
cout << "arr2的容量为:" << arr2.getCapacity() << endl;
cout << "arr2的大小为:" << arr2.getSize() << endl;
cout << "arr2的打印输出为:" << endl;
printIntArray(arr2);
}
//测试自定义数据类型
class Person
{
public:
Person() {};
Person(string name, int age)
{
this->m_age = age;
this->m_name = name;
}
string m_name;
int m_age;
};
void printPersonArray(MyArray& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << "Name: " << arr[i].m_name << "\tAge: " << arr[i].m_age << endl;
}
}
void test02()
{
MyArray arr(10);
Person p1("孙悟空", 999);
Person p2("韩信", 20);
Person p3("妲己", 50);
Person p4("安琪拉", 99);
Person p5("赵云", 9);
//将数据插入到数组中
arr.Push_Back(p1);
arr.Push_Back(p2);
arr.Push_Back(p3);
arr.Push_Back(p4);
arr.Push_Back(p5);
//打印数组
printPersonArray(arr);
//输出容量和大小
cout << "arr的容量为:" << arr.getCapacity() << endl;
cout << "arr的大小为:" << arr.getSize() << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器
容器:置物之所也。
STL容器就是将运用最广泛的一些数据结构实现出来。
常用的数据结构:数组、链表、树、栈、队列、集合、映射表等。
这些容器分为序列式容器和关联式容器两种:
算法:问题之解法也。
有限的步骤,解决逻辑或数学上的问题。
算法分为:质变算法和非质变算法。
质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝、替换、删除等。
非质变算法:是指运算过程中不会更改区间内的元素的内容。例如查找、计数、遍历、寻找极值等。
迭代器:容器和算法之间粘合剂。
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器内部表示方式。
每个容器都有自己的专属迭代器。
迭代器非常类似于指针,初学阶段可以先理解迭代器为指针。
迭代器种类:
常用的容器中迭代器种类为双向迭代器和随机访问迭代器。
容器:vector
算法:for_each
迭代器:vector
示例:
#include
#include
#include
using namespace std;
void myPrint(int val)
{
cout << val << endl;
}
//vector容器存放内置数据类型
void test01()
{
//创建了一个vector容器,数组
vector v;
//向容器中插入数据
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
//通过迭代器访问容器中的数据
//vector::iterator itBeign = v.begin();//起始迭代器,指向容器中第一个元素
//vector::iterator itEnd = v.end(); //结束迭代器,指向容器中最后一个元素的下一个位置
第一种遍历方式
//while (itBeign != itEnd)
//{
// cout << *itBeign << endl;
// itBeign++;
//}
//第二种遍历方式
/*for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}*/
//第三种遍历方式 利用STL中提供的遍历算法
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
#include
#include
using namespace std;
//vector容器中存放自定义数据类型
class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}
string m_name;
int m_age;
};
void test01()
{
vector v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
Person p5("eee", 50);
//向容器中添加数据
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
//遍历容器中的数据
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it).m_name << "\t年龄:" << (*it).m_age << endl;
}
//*it类型就是尖括号内类型 这里*it类型就是Person类型
}
//存放自定义数据类型指针
void test02()
{
vector v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
Person p5("eee", 50);
//向容器中添加数据
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
v.push_back(&p5);
//遍历容器
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it)->m_name << "\t年龄:" << (*it)->m_age << endl;
}
//*it类型就是尖括号内类型 这里*it类型就是Person*类型
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
#include
using namespace std;
#include
//容器嵌套容器
void test01()
{
vector>v;
//创建小容器
vectorv1;
vectorv2;
vectorv3;
vectorv4;
//向小容器中添加数据
for (int i = 0; i < 4; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
v4.push_back(i + 4);
}
//将小容插入到大的容器中
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
//通过大容器,把所有数据遍历一遍
for (vector>::iterator it = v.begin(); it != v.end(); it++)
{
//(*it)======容器vector
for (vector::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
cout << *vit << " ";
}
cout << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
本质:string是C++ 风格字符串,而string本质上是一个类
string和char*区别:
特点:
string内部封装了很多成员方法
例如,查找find、拷贝copy、删除delete、替换replace、插入insert
string管理char *所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责
构造函数原型:
#include
using namespace std;
//string的构造函数
void test01()
{
string s1;
const char* str = "Hello World";
string s2(str);
cout << "s2 = " << s2 << endl;
string s3(s2);
cout << "s3 = " << s3 << endl;
string s4(10, 'a');
cout << "s4 = " << s4 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:给string字符串进赋值
赋值的函数原型:
示例:
#include
using namespace std;
void test01()
{
string str1;
str1 = "Hello World";
cout << "str1 = " << str1 << endl;
string str2 = str1;
cout << "str2 = " << str2 << endl;
string str3;
str3= 'a';
cout << "str3 = " << str3 << endl;
string str4;
str4.assign("Hello C++");
cout << "str4 = " << str4 << endl;
string str5;
str5.assign("Hello C++", 5);
cout << "str5 = " << str5 << endl;
string str6;
str6.assign(str5);
cout << "str6 = " << str6 << endl;
string str7;
str7.assign(10, 'w');
cout << "str7 = " << str7 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:实现在字符串末尾拼接字符串
函数原型:
示例:
#include
using namespace std;
void test01()
{
string str1 = "我";
str1 += "爱玩游戏";
cout << "str1 = " << str1 << endl;
str1 += ":";
cout << "str1 = " << str1 << endl;
string str2 = " LOL DNF";
str1 += str2;
cout << "str1 = " << str1 << endl;
string str3 = "I";
str3.append(" Love");
cout << "str3 = " << str3<< endl;
str3.append(" Game abcde", 5);
cout << "str3 = " << str3 << endl;
str3.append(str2);
cout << "str3 = " << str3 << endl;
str3.append(str2, 0, 4); //参数2从那个位置截取 参数3是要截取的参数个数
cout << "str3 = " << str3 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:
函数原型:
示例:
#include
using namespace std;
//字符串的查找和替换
//1.查找
void test01()
{
string str1 = "abcdefg";
int pos = str1.find("de");
if (pos == -1)
{
cout<<"未找到字符串!"<
总结:
功能描述:字符串之间比较
比较方式:
函数原型:
#include
using namespace std;
//字符串比较
void test01()
{
string str1 = "xello";
string str2 = "hello";
if (str1.compare(str2) == 0)
{
cout << "str1 = str2" << endl;
}
else if (str1.compare(str2) > 0)
{
cout << "str1 > str2" << endl;
}
else
{
cout << "str1 < str2" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
总结:字符串比较主要用于判断两个字符串是不是想等,比较谁打谁小意义不大。
string中单个字符的提取有两种方式
#include
using namespace std;
//string字符提取
void test01()
{
string str = "hello";
cout << "str = " << str << endl;
//1.通过[]访问单个字符
for (int i = 0; i < str.size(); i++)
{
cout << str[i] << " ";
}
cout << endl;
//2.通过at方式访问单个字符
for (int i = 0; i < str.size(); i++)
{
cout << str.at(i) << " ";
}
cout << endl;
//修改单个字符
str[0] = 'x';
cout << "str = " << str << endl;
str.at(1) = 'x';
cout << "str = " << str << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对string字符串进行插入和删除字符操作
函数原型:
//string& insert(int pos, const char* s); //插入字符串
//string& insert(int pos, const string& str); //插入字符串
//string& insert(int pos, int n, char c); //在指定位置插入n个字符c
//string& erase(int pos, int n = npos); //删除从pos开始的n个字符
#include
using namespace std;
void test01()
{
string str = "hello";
//插入
str.insert(1, "111");
cout << "str = " << str << endl;
//删除
str.erase(1, 3);
cout << "str = " << str << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:插入和删除起始下标都是从0开始
功能描述:从字符串中获取想要的子串
函数原型:string substr(iny pos = 0,int n = npos)const; //返回由pos开始的n个字符组成的字符串
示例:
#include
using namespace std;
//string求子串
void test01()
{
string str = "abcdef";
string subStr = str.substr(1, 3);
cout << "subStr = " << subStr << endl;
}
//实用操作
void test02()
{
string email = "[email protected]";
//从邮件中获取用户名信息
int pos = email.find("@");
string userName = email.substr(0, pos);
cout << "userName = " << userName << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:灵活的运用求子串功能,可以在实际开发中获取有效信息。
功能:vector数据结构和数组非常相似,也称为单端数组
vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展:
功能描述:创建vector容器
函数原型:
示例:
#include
using namespace std;
#include
void printVector(vector &v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器的构造
void test01()
{
vector v1; //默认构造 无参构造
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//通过区间方式构造
vectorv2(v1.begin(), v1.end());
printVector(v2);
//n个elem方式构造
vector v3(10, 100);
printVector(v3);
//拷贝构造
vector v4(v3);
printVector(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:给vector容器进行赋值
函数原型:
示例:
#include
#include
using namespace std;
void printVector(vector &v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector的赋值
void test01()
{
vector v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//赋值 operator=
vectorv2 = v1;
printVector(v2);
//assign
vector v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
//assign n个elem
vector v4;
v4.assign(10, 100);
printVector(v4);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对vector容器的容量和大小操作
函数原型:
#include
#include
using namespace std;
void printVector(vector& v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器容量和大小
void test01()
{
vector 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的容量为:" << v1.capacity() << endl;
cout << "v1的大小为:" << v1.size() << endl;
}
//重新指定大小
v1.resize(15,100); //利用重载版本,可以指定默认填充值,参数2
printVector(v1);
v1.resize(16);
printVector(v1); //如果重新指定过长,默认用0填充新的位置
v1.resize(5);
printVector(v1); //如果重新指定的比原来的短了,超出部分会删掉
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对vector容器进行插入和删除操作
函数原型:
示例:
#include
#include
using namespace std;
//vector插入和删除
//push_back(ele); //尾部插入元素ele
//pop_back(); //删除最后一个元素
//insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
//insert(const_iterator pos, int count, ele); //迭代器指向位置pos插入count个元素ele
//erase(const_iterator pos); //删除迭代器指向的元素
//erase(const_iterator start, const_iterator end); //删除迭代器从start到end之间的元素
//clear(); //删除容器中所有元素
void printVector(vector &v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector v1;
//尾插
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
//遍历
printVector(v1);
//尾删
v1.pop_back();
printVector(v1);
//插入 第一个参数是迭代器
v1.insert(v1.begin(), 100);
printVector(v1);
v1.insert(v1.begin(), 2, 1000);
printVector(v1);
//删除
v1.erase(v1.begin());
printVector(v1);
//v1.erase(v1.begin(), v1.end()); //类似于clear()
v1.clear();
printVector(v1);
}
int main()
{
test01();
system("pause");
return 0;
}
总结:
功能描述:对vector中的数据的存取操作
函数原型:
#include
#include
using namespace std;
//vector容器——数据存取
void test01()
{
vector 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 << "第一个元素为:" << v1.front() << endl;
//获取最后一个元素
cout << "最后一个元素为:" << v1.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:实现两个容器内元素进行互换
函数原型:
示例:
#include
#include
using namespace std;
//vector容器互换
void printVector(vector &v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//1.基本使用
void test01()
{
cout << "交换前:" << endl;
vector v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
vector v2;
for (int i = 10; i >0; i--)
{
v2.push_back(i);
}
printVector(v2);
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
//2.实际用途
//巧用swap可以收缩内存空间
void test02()
{
vectorv;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
}
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
v.resize(3);
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
//巧用swap收缩内存
vector(v).swap(v);
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:swap可以使两个容器互换,可以达到实用的收缩内存效果。
笔记:
vector
功能描述:减少vector在动态扩展容量时的扩展次数
函数原型:
示例:
#include
#include
using namespace std;
//vector容器预留空间
void test01()
{
vector v;
//利用resreve预留空间
v.reserve(100000);
int num = 0; //统计开辟次数
int* p = NULL;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
if(p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "num = " << num << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:如果数据量较大,可以一开始就用reserve预留空间。
功能:双端数组,可以对头端进行插入删除操作
deque与vector区别:
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区的内容,缓冲区存放真实数据
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
deque容器的迭代器也是支持随机访问的。
功能描述:deque容器构造
函数原型:
示例:
#include
#include
using namespace std;
//deque容器构造函数
void printDeque(const deque& d)
{
for (deque::const_iterator it = d.begin(); it != d.end(); it++)
{
//*it = 100; //限定为只读状态,容器里的数据不可以修改了
cout << *it << " ";
}
cout < d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
deque d2(d1.begin(), d1.end());
printDeque(d2);
dequed3(10, 100);
printDeque(d3);
deque d4(d3);
printDeque(d4);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:给deque容器进行赋值
函数原型:
示例:
#include
#include
using namespace std;
//deque容器赋值操作
void printDeque(const deque &d)
{
for (deque::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
deque d2 = d1;
printDeque(d2);
deque d3(d1.begin(), d1.end());
printDeque(d3);
dequed4(10, 100);
printDeque(d4);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对deque容器的大小进行操作
函数原型:
示例:
#include
#include
using namespace std;
//deque容器-大小操作
void printDeque(const deque &d)
{
for (deque::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
if (d1.empty())
{
cout << "d1为空" << endl;
}
else
{
cout << "d1不为空!" << endl;
cout << "d1的大小为:" << d1.size() << endl;
}
//重新指定大小
d1.resize(15);
printDeque(d1);
d1.resize(20, 1);
printDeque(d1);
d1.resize(5);
printDeque(d1);
}
int main()
{
test01();
system("pause");
return 0;
}
总结:deque没有容量的概念。他是用中控器搞的。
功能描述:向deque容器中插入和删除数据
函数原型:
两端操作:
指定位置操作:
#include
#include
using namespace std;
//deque容器的插入和删除
void printDeque(const deque &d)
{
for (deque::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
dequed1;
//尾插
d1.push_back(10);
d1.push_back(20);
//头插
d1.push_front(100);
d1.push_front(200);
printDeque(d1);
//尾删
d1.pop_back();
printDeque(d1);
//头删
d1.pop_front();
printDeque(d1);
}
void test02()
{
deque d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);
printDeque(d1);
//insert插入
d1.insert(d1.begin(), 1000);
printDeque(d1);
d1.insert(d1.begin(), 2,10000);
printDeque(d1);
//按照区间进行插入
dequed2;
d2.push_back(1);
d2.push_back(2);
d2.push_back(3);
d1.insert(d1.begin(), d2.begin(), d2.end());
printDeque(d1);
}
void test03()
{
deque d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);
//删除
deque::iterator it = d1.begin();
it++;
d1.erase(it);
printDeque(d1);
//按照区间方式删除
d1.erase(d1.begin(), d1.begin() + 2);
printDeque(d1);
d1.clear();
printDeque(d1);
}
int main()
{
test01();
test02();
test03();
system("pause");
return 0;
}
总结:插入和删除提供的位置是迭代器。而非数字。即原型中pos为d.begin()等。
功能描述:对deque中的数据存取操作
函数原型:
#include
#include
using namespace std;
//deque数据存取
void test01()
{
deque d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(100);
d.push_front(200);
d.push_front(300);
//通过[]方式访问元素
for (int i = 0; i < d.size(); i++)
{
cout << d[i] << " ";
}
cout << endl;
//通过at方式访问元素
for (int i = 0; i < d.size(); i++)
{
cout << d.at(i)<< " ";
}
cout << endl;
cout << "第一个元素为:" << d.front ()<< endl;
cout << "最后一个元素为:" << d.back() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:除了用迭代器获取deque容器中的元素(遍历,输出*it),[]和at也可以
功能描述:利用算法实现对deque容器进行排序
算法:
示例:
#include
#include
#include //标准算法头文件
using namespace std;
//deque容器排序
void printDeque(const deque &d)
{
for (deque::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(100);
d.push_front(200);
d.push_front(300);
printDeque(d);
//排序 默认排序规则是升序
//对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
//vector容器也可以利用sort进行排序
sort(d.begin(), d.end());
printDeque(d);
}
int main()
{
test01();
system("pause");
return 0;
}
有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除最低分,取平均分。
示例代码:
#include
#include
#include
#include
#include
using namespace std;
//选手类
class Person
{
public:
Person(string name, int score)
{
m_name = name;
m_score = score;
}
string m_name;
int m_score;
};
void creatPerson(vector&v)
{
string nameSeed = "ABCDE";
for (int i = 0; i < 5; i++)
{
string name = " 选手";
name += nameSeed[i];
int score = 0;
Person p(name, score);
//将创建的Person对象放入到容器中
v.push_back(p);
}
}
//打分
void setScore(vector& v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
//将评委分数放入到deque容器中
deque d;
for (int i = 0; i < 10; i++)
{
int score = rand() % 41 + 60; //60-100
d.push_back(score);
}
//排序
sort(d.begin(), d.end());
//去除最高分和最低分
d.pop_back();
d.pop_front();
//取平均分
int sum = 0;
for (deque::iterator dit = d.begin(); dit != d.end(); dit++)
{
sum += *dit;
}
int avg = sum / d.size();
//将平均分赋值给选手
it->m_score = avg;
}
}
void showScore(vector &v)
{
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名:" << (*it).m_name << "\t分数:" << (*it).m_score << endl;
}
}
int main()
{
srand((unsigned int)time(NULL));
//1.创建五名选手
vector v; //存放选手的容器
creatPerson(v);
测试
//for (vector::iterator it = v.begin(); it != v.end(); it++)
//{
// cout << "姓名:" << (*it).m_name << "\t分数:" << (*it).m_score << endl;
//}
//2.给五名选手打分
setScore(v);
//3.显示最后得分
showScore(v);
system("pause");
return 0;
}
概念:stack是一种先进后出(First In Last Out,FILO)的数据结构,他只有一个出口
栈中只有顶端元素才能被外界使用,因此栈不允许有遍历行为
栈中进入数据称为——入栈push
栈中弹出数据称为——出栈pop
构造函数:
赋值操作:
数据存取:
大小操作:
示例:
#include
#include
using namespace std;
//stack常用接口
void test01()
{
//特点:符合先进后出数据结构
stack s;
//入栈
s.push(10);
s.push(20);
s.push(30);
s.push(40);
//只要栈不为空,查看栈顶并执行出栈操作
while(!s.empty())
{
//查看栈顶元素
cout << "栈顶元素为:" << s.top() << endl;
//出栈
s.pop();
}
cout << "栈的大小:" << s.size() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
概念:Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口
队列中只有队头和队尾才可以被外界是使用,因此队列不允许有遍历行为
队列中进数据称为——入队push
队列中出数据称为——出队pop
功能描述:栈容器常用的对外接口。
构造函数:
赋值操作:
数据存取:
大小操作:
示例:
#include
#include
using namespace std;
//队列
class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}
string m_name;
int m_age;
};
void test01()
{
queueq;
//准备数据
Person p1("唐僧", 30);
Person p2("孙悟空", 1000);
Person p3("猪八戒", 900);
Person p4("沙和尚", 800);
//入队
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
while (!q.empty())
{
//查看队头
cout << "队头元素——姓名:" << q.front().m_name << "\t年龄:" << q.front().m_age << endl;
cout << "队尾元素——姓名:" << q.back().m_name << "\t年龄:" << q.back().m_age << endl;
//出队
q.pop();
}
cout << "队列大小:" << q.size() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能:将数据进行链式存储
链表是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
链表的组成:链表由一系列结点组成
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表中的迭代器只支持前移和后移,属于双向迭代器。
list的优点:
list的缺点:
List有一个重要性质,插入和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。
总结:STL中List和Vector是两个最常被使用的容器,各有优缺点。
功能描述:创建list容器
函数原型:
示例:
#include
#include
using namespace std;
//list容器的构造
void printList(const list& L)
{
for (list::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list L1;
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//遍历容器
printList(L1);
//区间方式构造
list L2(L1.begin(), L1.end());
printList(L2);
//拷贝构造
list L3(L2);
printList(L3);
//n个elem
list L4(10, 1000);
printList(L4);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:给list容器进行赋值,以及交换list容器
函数原型:
示例:
#include
#include
using namespace std;
//list容器赋值和交换
void printList(const list& L)
{
for (list::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//赋值
void test01()
{
list L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
list L2;
L2 = L1; //operator=赋值
printList(L2);
list L3;
L3.assign(L2.begin(), L2.end());
printList(L3);
list L4;
L4.assign(10, 100);
printList(L4);
}
//交换
void test02()
{
list L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
list L2;
L2.assign(10, 100);
printList(L2);
cout << "交换后:" << endl;
L1.swap(L2);
printList(L1);
printList(L2);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
功能描述:对list容器的大小进行操作
函数原型:
示例:
#include
#include
using namespace std;
//list大小操作
void printList(const list &L)
{
for (list::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//判断容器是否为空
if (L1.empty())
{
cout << "L1为空!" << endl;
}
else
{
cout << "L1不为空!" << endl;
cout << "L1的元素个数为:" << L1.size() << endl;
}
L1.resize(10);
printList(L1);
L1.resize(15, 20);
printList(L1);
L1.resize(5);
printList(L1);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对list容器进行数据的插入和删除
函数原型:
#include
#include
using namespace std;
//list容器的插入和删除
void printList(const list &L)
{
for (list::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
printList(L);
//尾删
L.pop_back();
printList(L);
//头部删除
L.pop_front();
printList(L);
//insert插入
L.insert(++L.begin(), 1000);
printList(L);
//删除
L.erase(++L.begin());
printList(L);
//remove移除
L.push_back(10000);
printList(L);
L.remove(10000);
printList(L);
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
printList(L);
L.remove(10000);
printList(L);
L.clear();
printList(L);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对list容器中的数据进行存取
函数原型:
#include
#include
using namespace std;
//list容器中的数据存取
void test01()
{
list L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
cout << "第一个元素是:" << L1.front() << endl;
cout << "最后一个元素是:" << L1.back() << endl;
//L1[0] 不可以用[]访问list容器中的元素
//L1.at(0) 不可以用at方式访问list中的元素
//原因是list本质链表,不是用连续线性空间存储数据,迭代器也不是支持随机访问的
//验证迭代器是不支持随机访问的
list::iterator it = L1.begin();
it++; //支持双向
it--;
//it = it + 1; //不支持随机访问
}
int main()
{
test01();
system("pause");
return 0;
}
tips:
验证是否支持随机访问: it+1;不报错说明支持随机访问,报错说明不支持随机访问。
验证是单向还是双向:如果it++不报错it--报错说明是单向。如果都不报错说明支持双向。
功能描述:将容器中的元素反转,以及将容器中的数据进行排序。
函数原型:
示例:
#include
#include
using namespace std;
//list容器的反转和排序
void printList(const list& L)
{
for (list::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool Compare(int v1, int v2)
{
//降序 就让第二个数<第一个数。
return v1 > v2;
}
void test01()
{
list L1;
L1.push_back(20);
L1.push_back(10);
L1.push_back(50);
L1.push_back(40);
L1.push_back(30);
cout << "反转前:" << endl;
printList(L1);
//反转后
L1.reverse();
cout << "反转后:" << endl;
printList(L1);
}
//排序
void test02()
{
list L1;
L1.push_back(20);
L1.push_back(10);
L1.push_back(50);
L1.push_back(40);
L1.push_back(30);
cout << "排序前:" << endl;
printList(L1);
//排序后
//sort(L1.begin(), L1.end());//所有不支持随机访问的迭代器的容器,不可以用标准算法
//不支持随机访问迭代器的容器,内部会提供一些对应的算法,没法用全局函数,用成员函数即可
L1.sort();//默认排序规则是从小到大
cout << "排序后:" << endl;
printList(L1);
L1.sort(Compare);
printList(L1);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
案例描述:将Person自定义数据类型进行排序,Person中有姓名、年龄、身高
排序规则:按照年龄进行升序,如果年龄相同按身高进行排序
示例:
#include
#include
using namespace std;
//list容器排序案例
class Person
{
public:
Person(string name, int age, double height)
{
m_age = age;
m_name = name;
m_height = height;
}
string m_name;
int m_age;
double m_height;
};
//指定排序规则
bool Compare(Person &p1,Person &p2)
{
if (p1.m_age == p2.m_age)
{
return p1.m_height > p2.m_height;
}
return p1.m_age < p2.m_age;
}
void test01()
{
listL; //创建容器
//准备数据
Person p1("刘备", 35, 175.2);
Person p2("曹操", 45, 180.1);
Person p3("孙权", 40, 175.1);
Person p4("赵云", 25, 190.2);
Person p5("张飞", 35, 160.1);
Person p6("关羽", 35, 200.3);
//插入数据
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
for (list::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_name << "\t年龄:" << it->m_age << "身高:" << it->m_height << endl;
}
//排序
cout << "------------------------------------------------------" << endl;
cout << "排序后:" << endl;
L.sort(Compare);
for (list::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_name << "\t年龄:" << it->m_age << "身高:" << it->m_height << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
注意高级排序写法。
总结:
简介:所有元素都会在插入时被自动排序
本质:set和multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
功能描述:创建set容器以及赋值
构造:
赋值:
示例:
#include
#include
using namespace std;
void printSet(set &s)
{
for (set::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set s1;
//插入数据只有insert方式
s1.insert(10);
s1.insert(40);
s1.insert(30);
s1.insert(20);
s1.insert(30);
//遍历容器
//set容器特点:所有元素在插入的时候自动被排序
//set容器不允许插入重复值
printSet(s1);
//拷贝构造
set s2(s1);
printSet(s2);
//赋值操作
set s3;
s3 = s2;
printSet(s3);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述: 统计set容器大小以及交换set容器。
函数原型:
示例:
#include
#include
using namespace std;
//set容器大小和交换
//大小
void printSet(set& s)
{
for (set::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
if (s1.empty())
{
cout << "s1为空" << endl;
}
else
{
cout << "s1不为空" << endl;
cout << "s1的大小为:" << s1.size() << endl;
}
}
//交换
void test02()
{
set s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
set s2;
s2.insert(100);
s2.insert(200);
s2.insert(300);
s2.insert(400);
cout << "交换前" << endl;
printSet(s1);
printSet(s2);
cout << "交换后" << endl;
s1.swap(s2);
printSet(s1);
printSet(s2);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
功能描述:set容器进行插入和删除数据
函数原型:
示例:
#include
#include
using namespace std;
//set容器的插入和删除
void printSet(set& s)
{
for (set::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
set s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
//删除
s1.erase(s1.begin());
printSet(s1);
//删除重载版本
s1.erase(30);
printSet(s1);
s1.erase(s1.begin(), s1.end());
printSet(s1);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:对set容器进行查找数据以及统计数据
函数原型:
示例:
#include
#include
using namespace std;
//set容器-查找和统计
void test01()
{
set s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
//查找
set::iterator pos = s1.find(30);
if (pos != s1.end())
{
cout << "找到元素:" << *pos << endl;
}
else
{
cout << "未找到元素!" < s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(30);
s1.insert(30);
s1.insert(30);
s1.insert(40);
//统计30的个数
int num = s1.count(30);//对于set而言,统计的结果要么是0要么是1
cout << "number = " << num << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
区别:
示例:
#include
#include
using namespace std;
//set容器和multiset容器区别
void test01()
{
set s;
pair::iterator,bool> ret = s.insert(10);
if (ret.second)
{
cout << "第一次插入成功!" << endl;
}
else
{
cout << "第一次插入失败!" << endl;
}
ret = s.insert(10);
if (ret.second)
{
cout << "第二次插入成功!" << endl;
}
else
{
cout << "第二次插入失败!" << endl;
}
multiset ms;
//允许插入重复的值
ms.insert(10);
ms.insert(10);
for (multiset::iterator it = ms.begin(); it != ms.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:
功能描述:成对出现的数据,利用对组可以返回两个数据
两种创建方式:
示例:
#include
using namespace std;
//pair对组的创建
void test01()
{
//第一种方式
pairp("Tom", 20);
cout << "姓名:" << p.first << "\t年龄:" << p.second << endl;
//第二种方式
pairp2 = make_pair("Jerry", 30);
cout << "姓名:" << p2.first << "\t年龄:" << p2.second << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
主要技术点:利用仿函数,可以改变排序规则
示例一:set存放内置数据类型
#include
#include
using namespace std;
//set容器排序
class myCompare
{
public:
bool operator()(int v1,int v2)const
{
return v1 > v2;
}
};
void test01()
{
set s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(50);
s1.insert(30);
for (set::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//指定排序规则为从大到小
set s2; //仿函数
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(50);
s2.insert(30);
for (set::iterator it = s2.begin(); it != s2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:利用仿函数可以指定set容器的排序规则。
示例二:set存放自定义数据类型
#include
#include
using namespace std;
//set容器排序,存放自定义数据类型
class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}
string m_name;
int m_age;
};
class compare
{
public:
bool operator()(const Person &p1,const Person &p2)const
{
return p1.m_age > p2.m_age;
}
};
void test01()
{
set s;
Person p1("刘备", 24);
Person p2("关羽", 28);
Person p3("张飞", 25);
Person p4("赵云", 21);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set::iterator it = s.begin(); it != s.end(); it++)
{
cout << "姓名:" << it->m_name << "\t年龄:" << it->m_age << endl;
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:对于自定义数据类型,set必须指定排序规则才可以插入数据。
简介:
本质:map/multimap属于关联式容器,底层结构是用二叉树实现。
优点:可以根据key值快速找到value值。
map和multimap区别:
功能描述:对map容器进行构造和赋值
函数原型:
构造:
赋值:
#include
#include
总结:map中所有元素都是成对出现,插入数据要使用对组
功能描述:统计map容器大小以及交换map容器
函数原型:
示例:
#include
#include
函数原型:
示例:
#include
#include
功能描述:对map容器进行查找数据以及统计数据。
函数原型:
示例:
#include
#include
总结:
学习目标:map容器默认排序规则为按key值进行从小到大排序,掌握如何改变排序规则
主要技术点:利用仿函数,可以改变排序规则
示例:
#include
#include
总结:
3.10.2实现步骤:
案例代码:
#include
#include
#include
概念:
本质:
函数对象(仿函数) 是一个类,不是一个函数
特点:
#include
using namespace std;
//函数对象(仿函数)
//函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
//函数对象超出普通函数的概念,函数对象可以有自己的状态
//函数对象可以作为参数传递
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
//1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
void test01()
{
MyAdd myadd;
cout << myadd(10, 10) << endl;
}
//2.函数对象超出普通函数的概念,函数对象可以有自己的状态
class MyPrint
{
public:
MyPrint()
{
count = 0;
}
void operator()(string test)
{
cout << test << endl;
count++;
}
int count;
};
void test02()
{
MyPrint myprint;
myprint("hello world!");
myprint("hello world!");
myprint("hello world!");
myprint("hello world!");
myprint("hello world!");
cout << "MyPrint调用次数为:" <
概念:
示例:
#include
#include
#include
using namespace std;
//一元谓词
//仿函数返回值类型是bool数据类型,称为谓词
class GreaterFive
{
public:
bool operator()(int val)
{
return val > 5;
}
};
void test01()
{
vector v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//查找容器中 有没有大于5的数字
vector::iterator it = find_if(v.begin(),v.end(),GreaterFive());//GreaterFive()匿名函数对象
if (it == v.end())
{
cout << "未找到" << endl;
}
else
{
cout << "找到了大于5的数字为:" << *it << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
示例:
#include
#include
#include
using namespace std;
//二元谓词
class myCompare
{
public:
bool operator()(int val1,int val2)
{
return val1 > val2;
}
};
void test01()
{
vector 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::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//使用函数对象改变算法策略 变为排序规则为降序
sort(v.begin(), v.end(), myCompare()); //myCompare()匿名函数对象
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
概念:STL内建了一些函数对象
分类:
用法:
功能描述:
仿函数原型:
示例:
#include
#include //内建函数对象头文件
using namespace std;
//内建函数对象 算数仿函数
//negate 一元仿函数 取反仿函数
void test01()
{
negate n;
cout << n(50) << endl;
}
//plus 二元仿函数 加法运算
void test02()
{
plusp;
cout << p(10, 10) << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:使用内建函数对象时,需要引入头文件#include
功能描述:实现关系对比
仿函数原型:
示例:
#include
#include
#include
#include
using namespace std;
//内建函数对象-关系仿函数
//大于-greater
class myCompare
{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
void test01()
{
vectorv;
v.push_back(10);
v.push_back(30);
v.push_back(40);
v.push_back(20);
v.push_back(50);
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//降序
//sort(v.begin(), v.end(), myCompare());
//greater()内建函数对象
sort(v.begin(), v.end(), greater());
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:关系仿函数中最常用的就是greater<>大于。
功能描述:实现逻辑运算
函数原型:
示例:
#include
#include
#include
#include
using namespace std;
//内建函数对象-逻辑仿函数
//逻辑非-logical_not
void test01()
{
vector v;
v.push_back(true);
v.push_back(false);
v.push_back(true);
v.push_back(false);
for (vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//利用逻辑非 将容器v搬运到v2中,并执行取反操作
vector v2;
v2.resize(v.size()); //先开辟空间才能搬运
transform(v.begin(), v.end(), v2.begin(), logical_not());
for (vector::iterator it = v2.begin(); it != v2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:逻辑仿函数应用较少,了解即可。
概述:
算法简介:
#include
#include
#include
using namespace std;
//常用遍历算法 for_each
//普通函数
void print01(int val)
{
cout << val << " ";
}
//仿函数
class print02
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vectorv;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), print01); //对于普通函数来说,第三个参数放函数名
cout << endl;
for_each(v.begin(), v.end(), print02()); //对于仿函数来说,第三个参数放函数对象
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:for_each在实际开发中是最常用的遍历算法,需要熟练掌握。
功能描述:搬运容器到另一个容器
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用的遍历算法 transform
class Transform
{
public:
int operator()(int v)
{
return v+100;
}
};
class MyPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector vTarget;
vTarget.resize(v.size()); //目标容器 需要提前开辟空间
transform(v.begin(), v.end(), vTarget.begin(), Transform());
for_each(vTarget.begin(), vTarget.end(), MyPrint());
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:搬运的目标容器必须要提前开辟空间,否则无法正常搬运
算法简介:
功能描述:查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()
函数原型:find(iterator beg,iterator end,value);//按值查找元素,找到返回指定迭代器,找不到返回结束迭代器
//beg 开始迭代器
//end 结束迭代器
//value 查找的元素
示例:
#include
#include
#include
using namespace std;
//常用查找算法 - find
//查找 内置数据类型
void test01()
{
vectorv;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//查找容器中是否有5这个元素
vector::iterator it = find(v.begin(), v.end(), 5);
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了:" << *it << endl;
}
it = find(v.begin(), v.end(), 50);
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了:" << *it << endl;
}
}
//查找自定义数据类型
class Person
{
public:
Person(string name, int age)
{
m_age = age;
m_name = name;
}
//重载==号
bool operator==(const Person& p)
{
if (m_age == p.m_age && m_name == p.m_name)
return true;
else
return false;
}
string m_name;
int m_age;
};
void test02()
{
vectorv;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
Person pp("bbb", 20);
vector::iterator it = find(v.begin(), v.end(), pp);
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了! 姓名:" << it->m_name<<"\t年龄:"<m_age<< endl;
}
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:find可以在容器中找指定的元素,返回值是迭代器
功能描述:按条件查找元素
函数原型:
//按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置。
//beg开始迭代器
//end结束迭代器
//_pred函数或者谓词(返回bool类型的仿函数)
示例:
#include
#include
#include
using namespace std;
//常用查找算法-find_if
//1.查找内置数据类型
class GreaterFive
{
public:
bool operator()(int val)
{
return val > 5;
}
};
void test01()
{
vector v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector::iterator it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end())
{
cout << "未找到" << endl;
}
else
{
cout << "找到了 数字为:" << *it << endl;
}
}
//2.查找自定义数据类型
class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}
string m_name;
int m_age;
};
class Greater20
{
public:
bool operator()(Person& p)
{
return p.m_age > 20;
}
};
void test02()
{
vector v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
//年龄大于20
vector::iterator it = find_if(v.begin(), v.end(), Greater20());
if (it == v.end())
{
cout << "未找到" << endl;
}
else
{
cout << "找到了 姓名:" << it->m_name<<"\t年龄:"<m_age << endl;
}
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
功能描述:查找相邻重复元素
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用的查找算法-adjacent_find
void test01()
{
vector v;
v.push_back(0);
v.push_back(2);
v.push_back(0);
v.push_back(3);
v.push_back(1);
v.push_back(4);
v.push_back(3);
v.push_back(3);
vector::iterator pos = adjacent_find(v.begin(), v.end());
if (pos == v.end())
{
cout << "未找到相邻重复元素" << endl;
}
else
{
cout << "找到相邻重复元素: " << *pos << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
总结:面试题中如果出现了查找相邻重复元素的题目,记得用STL中的adjacent_find算法。
功能描述:查找指定元素是否存在
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用查找算法 binary_research
void test01()
{
vector v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//查找容器中是否有9元素
//注意容器必须是有序的数列
bool result = binary_search(v.begin(), v.end(), 9);
if (result)
{
cout << "找到了元素" <
总结:二分查找法查找效率高,值得注意的是查找的容器元素必须是有序序列。
功能:统计元素个数
函数原型:
示例:
#include
#include
using namespace std;
//常用统计算法-count
//1.统计内置数据类型
void test01()
{
vector v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(20);
v.push_back(40);
int num = count(v.begin(), v.end(), 40);
cout << "40元素的个数为" << num << endl;
}
//2.统计自定义数据类型
class Person
{
public:
Person(string name, int age)
{
m_age = age;
m_name = name;
}
bool operator == (const Person& p)
{
if (m_age == p.m_age)
{
return true;
}
else
{
return false;
}
}
string m_name;
int m_age;
};
void test02()
{
vectorv;
Person p1("刘备" ,35);
Person p2("关羽" ,35);
Person p3("张飞" ,35);
Person p4("赵云" ,30);
Person p5("曹操" ,40);
Person p("诸葛亮", 35);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
int num = count(v.begin(), v.end(), p);
cout << "与诸葛亮一样岁数的人有多少个:" << num << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
总结:统计自定义数据类型,需要配合重载operator==
功能:按条件同级元素个数
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用统计算法-count_if
//1.统计内置数据类型
class Greater20
{
public:
bool operator()(int val)
{
return val > 20;
}
};
void test01()
{
vector v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(20);
int num = count_if(v.begin(), v.end(), Greater20());
cout << "大于20的元素个数为" << num << endl;
}
//2.统计自定义数据类型
class Person
{
public:
Person(string name, int age)
{
m_age = age;
m_name = name;
}
string m_name;
int m_age;
};
class AgeGreater20
{
public:
bool operator()(const Person &p)
{
return p.m_age > 20;
}
};
void test02()
{
vectorv;
Person p1("刘备", 35);
Person p2("关羽", 35);
Person p3("张飞", 35);
Person p4("赵云", 30);
Person p5("曹操", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
int num = count_if(v.begin(), v.end(), AgeGreater20());
cout << "大于20岁的人员人数为:" << num << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
算法简介:
功能描述:对容器内元素进行排序
函数原型:
示例:
#include
#include
#include
#include
using namespace std;
//常用排序算法-sort
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector 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());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
//改变为降序
sort(v.begin(), v.end(), greater());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:洗牌 指定范围内的元素随机调整次序
函数原型:
示例:
#include
#include
#include
using namespace std;
#include
//常用排序算法 random_shuffle
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
srand((unsigned int)time(NULL));
vector v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//利用洗牌算法打乱顺序
random_shuffle(v.begin(), v.end());
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
总结:random_shuffle洗牌算法比较实用,使用时记得加随机种子。
功能描述:两个容器元素合并,并存储到另一个容器中。
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用排序算法 merge
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v1;
vectorv2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 1);
}
//目标容器
vector v;
v.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:将容器内元素进行反转
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用排序算法 reverse
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v;
v.push_back(10);
v.push_back(30);
v.push_back(50);
v.push_back(40);
v.push_back(20);
cout << "反转前:" << endl;
for_each(v.begin(), v.end(), myPrint);
cout << endl;
reverse(v.begin(), v.end());
cout << "反转后:" << endl;
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结: reverse反转指定区间内元素,面试题可能用到
学习目标:掌握常用的拷贝和替换算法。
算法简介:
功能描述:容器内指定范围的元素拷贝到另一个容器中
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用拷贝和替换算法-copy
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
vector v2;
v2.resize(v1.size());
copy(v1.begin(), v1.end(), v2.begin());
for_each(v2.begin(), v2.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
总结:利用copy算法拷贝时,记得提前给目标容器开辟空间
功能描述:将容器内指定范围的就元素改为新元素
函数原型:replace(iterator beg,iterator end,oldvalue,newvalue);
示例:
#include
#include
#include
using namespace std;
//常用拷贝和替换算法 replace
class myPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector v;
v.push_back(20);
v.push_back(30);
v.push_back(50);
v.push_back(30);
v.push_back(40);
v.push_back(20);
v.push_back(10);
v.push_back(20);
cout << "替换前:" << endl;
for_each(v.begin(), v.end(), myPrint());
cout << endl;
replace(v.begin(), v.end(), 20, 2000);
cout << "替换后:" << endl;
for_each(v.begin(), v.end(), myPrint());
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:将区间内满足条件的元素,替换成指定元素。
函数原型:
示例:
#include
using namespace std;
#include
#include
//常用拷贝和替换算法 replace_if
class myPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
class Greater30
{
public:
bool operator()(int val)
{
return val >= 30;
}
};
void test01()
{
vector v;
v.push_back(10);
v.push_back(20);
v.push_back(40);
v.push_back(40);
v.push_back(30);
v.push_back(50);
v.push_back(20);
v.push_back(10);
v.push_back(20);
cout << "替换前:" <
功能描述:互换两个容器的元素
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用拷贝和替换算法-swap
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v1;
vector v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 100);
}
cout << "交换前:" << endl;
for_each(v1.begin(), v1.end(), myPrint);
cout << endl;
for_each(v2.begin(), v2.end(), myPrint);
cout << endl;
swap(v1, v2);
cout << "交换后:" << endl;
for_each(v1.begin(), v1.end(), myPrint);
cout << endl;
for_each(v2.begin(), v2.end(), myPrint);
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:swap交换容器时,注意交换的容器要同种类型。
注意:算数生成算法属于小型算法,使用时包含头文件#include
算法简介:
功能描述:计算区间内 容器累计之和
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用的算术生成算法
void test01()
{
vector v;
for (int i = 0; i <= 100; i++)
{
v.push_back(i);
}
int total = accumulate(v.begin(), v.end(), 0);
cout << total << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:向容器中填充指定的元素
函数原型:
示例:
#include
#include
#include
#include
using namespace std;
//常用算术生成算法-fill
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v;
v.resize(10);
//后期重新填充
fill(v.begin(), v.end(), 100);
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
算法简介:
功能描述:求两个集合的交集
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用集合算法-set_intersection
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v1;
vector v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
vector v;
v.resize(min(v1.size(),v2.size()));
vector::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
for_each(v.begin(), itEnd, myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
总结:
功能描述:求两个集合的并集
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用集合算法-set_union
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v1;
vector v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
vector v;
v.resize(v1.size()+v2.size());
vector::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
for_each(v.begin(), itEnd, myPrint);
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:
功能描述:求两个集合的差集
函数原型:
示例:
#include
#include
#include
using namespace std;
//常用集合算法 set_difference
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector v1;
vector v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
vector v;
v.resize(max(v1.size(), v2.size()));
//v1-v2
vector::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
cout << "v1-v2:";
for_each(v.begin(), itEnd, myPrint);
cout << endl;
//v2-v1
itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v.begin());
cout << "v2-v1:";
for_each(v.begin(), itEnd, myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
总结: