目录
1 函数模板
1.1 函数模板基本语法
1、建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来代表。
2、语法:
template<typename T>//声明一个模板,T是一个通用的数据类型
函数声明或定义
#include <iostream>
using namespace std;
template<typename T>//声明一个模板,T是一个通用的数据类型
void mySwap(T &a, T &b)//
{
T temp = a;
a = b;
b = temp;
}
int main()
{
int a = 10;
int b = 20;
// 自动类型推导:必须要推导出一致的数据类型 T,模板必须要确定出T的数据类型
mySwap(a, b);
// 显示指定类型
mySwap<int>(a,b);
cout << a << b << endl;
}
1.2 函数模板注意事项
1、自动类型推导,必须推导出一致的数据类型T,才可以使用;
2、模板必须要确定出T的数据类型,才可以使用。
#include <iostream>
using namespace std;
template<typename T>//typename可以替换成class
void mySwap(T &a, T &b)//
{
T temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 0;
int b = 0;
char c = 'c';
mySwap(a, b);
//mySwap(a, c);错误,推导不出一致的T类型
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
template<class T>
void func()
{
cout << "func 调用" << endl;
}
void test02()
{
//func(); 错误,没有指定出T
func<int>();
}
int main()
{
test01();
test02();
}
1.3 函数模板案例—数组排序
1、实现一个通用 对数组进行排序的函数
2、规则 从大到小
3、算法 冒泡
4、测试数组 char数组 int数组
#include <iostream>
using namespace std;
//实现一个通用 对数组进行排序的函数
//规则 从大到小
//算法 冒泡
//测试数组 char数组 int数组
template<class T>
void printArray(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
/*template<typename T>*///typename可以替换成class
//void mySwap(T& a, T& b)//
//{
// T temp = a;
// a = b;
// b = temp;
//}不知道为什么,这里用这个交换没有办法排序
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])
{
/*mySwap(arr[j], arr[i]);*/
T temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void test01()
{
char charArr[] = "abcdef";
int num = sizeof(charArr) / sizeof(char);
mySort(charArr, num);
printArray(charArr, num);
}
void test02()
{
int intArray[] = { 0,3,4,6,2,8,9 };
int num = sizeof(intArray) / sizeof(int);
mySort(intArray, num);
printArray(intArray, num);
}
int main()
{
test01();
test02();
return 0;
}
1.4 普通函数与函数模板的区别
1、普通函数调用可以发生隐式类型转换;
2、函数模板 用自动类型推导,不可以发生隐式类型转换
3、函数模板 用显示指定类型,可以发生隐式类型转换
#include<iostream>
using namespace std;
int myAdd01(int a, int b)
{
return a + b;
}
void test01()
{
int a = 10;
int b = 20;
char c = 'c';
cout << myAdd01(a, b) << endl;
cout << myAdd01(a, c) << endl;//普通函数可以隐式转换
}
template<class T>
T myAdd02(T a, T b)
{
return a + b;
}
void test02()
{
int a = 10;
int b = 20;
char c = 'c';
cout << myAdd02<int>(a, c) << endl;//
//cout << myAdd02(a, c) << endl;//函数模板 用自动类型推导,不可以发生隐式类型转换
}
int main()
{
test01();
test02();
return 0;
}
1.5 普通函数与函数模板调用规则
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, b = 20;
//myPrint(a,b);// 优先调用普通函数
// 通过空模板参数列表,强制调用函数模板
myPrint<>(a, b);
myPrint(a, b, 100);
//如果函数模板可以产生更好的匹配,优先调用函数模板
char c1 = 'a';
char c2 = 'b';
myPrint(c1, c2);//调用模板
}
int main()
{
test01();
return 0;
}
1.6 模板的局限性
模板不是万能的,有些特定数据类型,需要用具体化方式做特殊实现
利用具体化的模板,可以解决自定义类型的通用化
学习模板不是为了写模板,而是在STL能够运用系统提供的模板
#include<iostream>
using namespace std;
#include<string>
class Person
{
public:
int m_age;
string m_name;
Person(string name, int age)
{
this->m_name = name;
this->m_age = 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_name == p2.m_name && p1.m_age == p2.m_age)
{
return true;
}
else
{
return false;
}
}
void test01()
{
int a = 10;
int b = 10;
bool ret = myCompare(a, b);
if (ret == true)
{
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 == true)
{
cout << "p1=p2" << endl;
}
else
{
cout << "p1!=p2" << endl;
}
}
int main()
{
//test01();
test02();
return 0;
}
2 类模板
2.1 类模板语法
template<typename T>
类
#include <iostream>
using namespace std;
template<class NameType,class AgeType>
class Person
{
public:
NameType m_name;
AgeType m_age;
Person(NameType name, AgeType age)
{
this->m_name = name;
this->m_age = age;
}
void showPerson()
{
cout << "name = " << this->m_name << endl;
cout << "age = " << this->m_age << endl;
}
};
void test01()
{
Person<string, int> p1("Tom", 10);
p1.showPerson();
}
int main()
{
test01();
return 0;
}
2.2 类模板和函数模板的区别
1、类模板没有自动类型推导使用方式
2、类模板在模板参数列表中可以有默认参数
#include <iostream>
using namespace std;
template<class NameType, class AgeType = int>//告诉了默认是int,后面可以不写int
class Person
{
public:
NameType m_name;
AgeType m_age;
Person(NameType name, AgeType age)
{
this->m_name = name;
this->m_age = age;
}
void showPerson()
{
cout << "name = " << this->m_name << endl;
cout << "age = " << this->m_age << endl;
}
};
void test01()
{
//Person p("Tom", 10);//错误,无法用自动类型推导
Person<string, int> p("Tom", 10);//正确
}
void test02()
{
Person<string> p("Tom", 10);
}
int main()
{
test01();
test02();
return 0;
}
2.3 类模板中成员函数创建时机
1、普通类中的成员函数一开始就可以创建
2、类模板中的成员函数在调用时才创建
#include <iostream>
using namespace std;
class Person1
{
public:
void showPerson2()
{
cout << "Person1 show" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "Person2 show" << endl;
}
};
template<class T>
class Myclass
{
public:
T obj;
//类模板中的成员函数
void func1()
{
obj.showPerson1;//没有报错
}
void func2()
{
obj.showPerson2;
}
};
void test01()
{
Myclass<Person1>m;
m.func1();
//m.func2();调用的时候创建类模板成员函数
}
int main()
{
test01();
return 0;
}
2.4 类模板对象做函数参数
类模板实例化出的对象作为函数参数怎么传
1、指定传入类型——直接显示对象的数据类型
2、参数模板化——将整个对象中的参数变为模板进行传递
3、整个类模板化——将这个对象类型 模板化进行传递
#include<iostream>
using namespace std;
template<class T1, class T2>
class Person
{
public:
T1 m_name;
T2 m_age;
Person(T1 name, T2 age)
{
this->m_name = name;
this->m_age = age;
}
void showPerson()
{
cout << "name = " << this->m_name << endl;
cout << "age = " << this->m_age << endl;
}
};
// 1、指定传入类型——直接显示对象的数据类型
void printPerson1(Person<string,int>&p)
{
p.showPerson();
}
void test01()
{
Person<string, int>p("孙悟空", 100);
printPerson1(p);
}
//2、参数模板化——将整个对象中的参数变为模板进行传递
template<class T1,class T2>
void printPerson2(Person<T1, T2>& p)
{
p.showPerson();
cout << "T1的类型为: " << typeid(T1).name() << endl;
cout << "T2的类型为: " << typeid(T2).name() << endl;
}
void test02()
{
Person<string, int>p("猪八戒", 90);
printPerson2(p);
}
//3、将整个类模板化
template<class T>
void printPerson3(T &p)
{
p.showPerson();
cout << "T的类型为: " << typeid(T).name() << endl;
}
void test03()
{
Person<string, int>p("唐僧", 30);
printPerson3(p);
}
int main()
{
test03();
return 0;
}
2.5 类模板与继承
当类模板遇到继承时,需要注意以下几点
1、当子类继承父类是一个类模板时,子类在声明的时候,要指定出父类中的T的类型
2、如果不指定,编译器无法给子类分配内存
3、如果想灵活指定出父类中的T类型,子类也需变为类模板
#include<iostream>
using namespace std;
template<class T>
class Base
{
T m;
};
//class Son :public Base//错误,必须要知道父类中的T类型,才能继承给子类
class Son1 :public Base<int>
{
};
void test01()
{
Son1 s1;
}
//如果想灵活指定出父类中的T类型,子类也需变为类模板
template <class T1,class T2>
class Son2 :public Base<T2>
{
public:
Son2()
{
cout << "T1的类型为: " << typeid(T1).name() << endl;
cout << "T2的类型为: " << typeid(T2).name() << endl;
}
T1 obj;
};
void test02()
{
Son2<int, char>s2;//父类是int ,子类是char
}
int main()
{
test02();
return 0;
}
2.6 类模板成员函数的类外实现
#include<iostream>
using namespace std;
template<class T1,class T2>
class Person
{
public:
T1 m_name;
T2 m_age;
Person(T1 name, T2 age);
void showPerson();
};
//构造函数类外实现
template<class T1, class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
this->m_age = age;
this->m_name = name;
}
//成员函数的类外实现
template<class T1, class T2>
void Person<T1,T2>::showPerson()
{
cout << "姓名: " << this->m_name << "年龄: " << m_age << endl;
}
void test01()
{
Person<string, int>p("Tom", 20);
p.showPerson();
}
int main()
{
test01();
}
2.7 类模板分文件编写
问题: 类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
1、直接包含.cpp源文件
2、将声明和实习写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,不是强制的
#include <iostream>
using namespace std;
//1、直接包含源文件
//#include "person.cpp"
//
//2、将.h和.cpp中的内容写到一起,将后缀名改为.hpp文件
#include "person.hpp"
void test01()
{
Person<string, int>p("Jerry", 18);
p.showPerson();
}
int main()
{
test01();
return 0;
}
2.8 类模板与友元
掌握类模板配合友元函数的类内实现和类外实现
1、全局函数类内实现—直接在类内声明友元即可
2、全局函数类外实现—需要提前让编译器自动全局函数的存在
#include<iostream>
using namespace std;
//提前让编译器知道Person类存在
template<class T1, class T2>
class Person;
template<class T1, class T2>
void printPerson2(Person<T1, T2>p)//类外实现
{
cout << "姓名: " << p.m_name << " 年龄: " << p.m_age << endl;
}
//通过全局函数打印Person信息
template<class T1, class T2>
class Person
{
//全局函数 类内实现
friend void printPerson(Person<T1, T2>p)
{
cout << "姓名: " << p.m_name << " 年龄: " << p.m_age << endl;
}
//全局函数 类外实现,加空模版参数列表
//如果全局函数是类外实现,需要让编译器提前知道这个函数的存在
friend void printPerson2<>(Person<T1, T2>p);
private:
T1 m_name;
T2 m_age;
public:
Person(T1 name, T2 age)
{
this->m_age = age;
this->m_name = name;
}
};
void test01()
{
Person<string, int>p("John", 10);
printPerson(p);
printPerson2(p);
}
int main()
{
test01();
return 0;
}
2.9 类模板案例—数组类封装
拷贝构造函数是在构造的时候给对象赋初值用的,operate=运算符重载是构造函数完毕后要重新赋值的时候用的
.hpp文件
// 写一个通用的数组类
#pragma once
#include<iostream>
using namespace std;
template<class T>
class MyArray
{
private:
T* pAddress;//指针指向堆区开辟真实数组
int m_Capacity;//数组的容量
int m_Size;//数组的大小
public:
MyArray()
{
}
MyArray(int capacity)
{
cout << "MyArray有参构造" << endl;
this->m_Capacity = capacity;
this->m_Size = 0;
this->pAddress = new T[this->m_Capacity];
}
//拷贝构造
MyArray(const MyArray& arr)
{
cout << "MyArray拷贝构造" << endl;
this->m_Capacity = arr.m_Capacity;
this->m_Size = arr.m_Size;
//深拷贝
this->pAddress = new T[arr.m_Capacity];
//将arr中的数据都拷贝过来
for (int i = 0; i < this->m_Size; i++)
{
this->pAddress[i] = arr.pAddress[i];
}
}
//operator防止浅拷贝问题 a=b=c;
MyArray& operator=(const MyArray& arr)
{
cout << "MyArray的 operator = 调用" << endl;
//先判断原来堆区是否有数据,如果有先释放
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 < this->m_Size; i++)
{
this->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--;
}
//通过下标访问数组中的元素
T& operator[](int index)
{
//函数中返回引用,则传回的变量等同于用另一个名字直接使用该变量
//引用必须初始化,初始化后不能再改变指向
return this->pAddress[index];
}
//返回数组容量
int getCapacity()
{
return this->m_Capacity;
}
// 返回数组大小
int getSize()
{
return this->m_Size;
}
//析构
~MyArray()
{
cout << "MyArray的析构" << endl;
if (this->pAddress != NULL)
{
delete[] this->pAddress;
this->pAddress = NULL;
}
}
};
.cpp测试文件
#include<iostream>
using namespace std;
#include "MyArray.hpp"
void printIntArray(MyArray<int>& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << arr[i] << endl;
}
}
void test01()
{
MyArray <int>arr1(5);//有参
for (int i = 0; i < 5; i++)
{
arr1.Push_Back(i);//利用尾插法向数组中插入数据
}
cout << "arr1的打印输出为: " << endl;
printIntArray(arr1);
cout << "arr1的容量为: " << arr1.getCapacity() << endl;
cout << "arr1的大小为: " << arr1.getSize() << endl;
MyArray<int>arr2(arr1);//拷贝
printIntArray(arr2);
arr2.Pop_Back();//尾删
cout << "arr2尾删后的打印输出为: " << endl;
printIntArray(arr2);
cout << "arr1的容量为: " << arr2.getCapacity() << endl;
cout << "arr1的大小为: " << arr2.getSize() << endl;
//MyArray<int>arr3(100);
//arr3 = arr1;//operate=
}
//测试自定义数据类型
class Person
{
public:
string m_name;
int m_age;
Person() {};//一定要写这个,不然会报错
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
void showPerson()
{
cout << "name = " << this->m_name << endl;
cout << "age = " << this->m_age << endl;
}
};
void printPersonArray(MyArray<Person>& arr)
{
for (int i = 0; i < arr.getSize(); i++)
{
cout << "姓名: "<< arr[i].m_name <<"年龄: "<< arr[i].m_age << endl;
}
}
void test02()
{
MyArray<Person>arr(10);
Person p1("孙悟空",999);
Person p2("赵云", 45);
Person p3("安其拉", 23);
Person p4("韩信", 32);
Person p5("妲己", 14);
//将数据插入到数组
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();
return 0;
}
3 STL初识
3.1 STL的基本概念
1、STL (Standard Template Library,标准模板库)
2、STL从广义上分为:容器container,算法algorithm,迭代器iterator
3、容器和算法之间通过迭代器进行无缝连接
4、STL几乎所有的代码都采用了模板类或者模板函数
STL的六大组件:容器、算法、迭代器,仿函数,适配器,空间配置
1.容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
2.算法:各种常用的算法,如sort、find、copy、for_each等
3.迭代器:扮演了容器与算法之间的胶合剂。
4.仿函数:行为类似函数,可作为算法的某种策略。
5.适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。6.空间配置器:负责空间的配置与管理。
容器:置物之所也
STL容器就是将运用最广泛的一些数据结构实现出来常用的数据结构:数组,链表,树,栈,队列,集合,映射表等,这些容器分为序列式容器和关联式容器两种:
序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
算法:问题之解法也
有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)算法分为:质变算法和非质变算法。
质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等。迭代器:容器和算法之间粘合剂
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。每个容器都有自己专属的迭代器
迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针。
3.2 vector存放内置数据类型
容器:vector 算法:for_each 迭代器:vector<int>::iterator
三种遍历方式
#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>//标准算法头文件
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);
//通过迭代器访问容器中的数据
vector<int>::iterator itBegin = v.begin();//起始迭代器 指向容器中的第一个元素
vector<int>::iterator itEnd = v.end();//结束迭代器 指向容器中最后一个元素的下一个位置
//第一种遍历方式
while (itBegin != itEnd)
{
cout << *itBegin << endl;
itBegin++;
}
//第二种遍历方式 常用
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
//第三种遍历方式 利用STL提供的遍历算法
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
return 0;
}
3.3 vector存放自定义数据类型
for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it)->m_name << " 年龄: " << (*it)->m_age << endl;
//尖括号里是声明*it就是什么
}
#include<iostream>
using namespace std;
#include<vector>
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
void test01()
{
vector<Person>v;
Person p1("aa", 10);
Person p2("bb", 10);
Person p3("cc", 10);
Person p4("dd", 10);
Person p5("ee", 10);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it).m_name << " 年龄: " << (*it).m_age << endl;
cout << "姓名: " << it->m_name<< " 年龄: " << it->m_age << endl;
}
}
//存放自定义数据类型 指针
void test02()
{
vector<Person*>v;
Person p1("aa", 10);
Person p2("bb", 20);
Person p3("cc", 30);
Person p4("dd", 40);
Person p5("ee", 50);
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
v.push_back(&p5);
for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it)->m_name << " 年龄: " << (*it)->m_age << endl;
//尖括号里是声明*it就是什么
}
}
int main()
{
//test01();
test02();
return 0;
}
3.4 容器嵌套容器
#include<iostream>
using namespace std;
#include<vector>
void test01()
{
vector<vector<int>>v;
//先创建小容器
vector<int>v1;
vector<int>v2;
vector<int>v3;
vector<int>v4;
//向小容器中添加数据
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<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
{
//*it是一个容器
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
cout << *vit << " ";
}
cout << endl;
}
}
int main()
{
test01();
return 0;
}
4 string容器
4.1 构造函数
#include <iostream>
using namespace std;
// string(); 创建一个空的字符串例如: string str;
// string(const char* s); 使用字符串s初始化
// string(const string& str); 使用一个string对象初始化另一个string对象
// string(int n, char c); 使用n个字符c初始化
void test01()
{
const char* str = "hello world";
string s1;//默认构造
string s2(str);
string s3(s2);
string s4(10, 'a');
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
cout << "s4 = " << s4 << endl;
}
int main()
{
test01();
return 0;
}
4.2 赋值操作
#include <iostream>
using namespace std;
//string& operator=(const char* s); char* 类型字符串赋值给当前的字符串
//string& operator=(const string& s); 把字符串s赋给当前的字符串
//string& operator=(char c); 字符赋值给当前的字符串
//string & assign(const char* s); 把字符串s赋给当前的字符串
//string& assign(const char* s, int n); 把字符串s的前n个字符赋给当前的字符串
//string& assign( const string &s ); 把字符串s赋给当前字符串
//string& assign(int n, char c); 用n个字符c赋给当前字符串
void test01()
{
string s1;
s1 = "hello world";
cout << s1 << endl;
string s2 = s1;
cout << s2 << endl;
string s3;
s3 = 'c';
cout << s3 << endl;
string s4;
s4.assign("hello C++");
cout << s4 << endl;
string s5;
s5.assign("hello C++", 5);
cout << s5 << endl;
string s6;
s6.assign(s5);
cout << s6 << endl;
string s7;
s7.assign(5, 'a');
}
int main()
{
test01();
return 0;
}
4.3 字符串拼接
#include<iostream>
using namespace std;
/*
string& operator+=(const char* str); //重载+=操作符
string& operator+=( const char c); //重载+=操作符
string& operator+=( const string& str); //重载+=操作符
string& append( const char *s); //把字符串s连接到当前字符串结尾
string& append(const char*s, int n); //把字符串s的前n个字符连接到当前字符串结尾
string& append(const string &s); //同operator+=(const string& str)
string&append(const string &s, int pos,int n);//字符串s中从pos开始的n个字符连接到字符串结
*/
void test01()
{
string str1 = "我";
str1 += "不爱玩游戏,爱学习";
cout << str1 << endl;
str1 += ':';
string str2 = "看柯南";
str1 += str2;
cout << str2 << endl;
string str3 = "I";
str3.append("love");
cout << str3 << endl;
str3.append(str2);
cout << str3 << endl;
string str4 = "learning aaa";
str3.append(str4, 0, 8);
cout << str3 << endl;
}
int main()
{
test01();
return 0;
}
4.4 字符串查找和拼接
#include<iostream>
using namespace std;
//查找
void test01()
{
string str1 = "abcdefgde";
int pos1 = str1.find("de");
int pos2 = str1.find("df");
cout << pos1 << endl;
cout << pos2 << endl;//没有找到字串返回 -1
//rfind 从右往左查,但是从左往右计算位置
int pos3 = str1.rfind("de");
cout << pos3 << endl;
}
//替换
void test02()
{
string str1 = "Abcdefg";
str1.replace(1, 3, "1111");//从1号位置起,替换为“1111”
cout << str1 << endl;
}
int main()
{
//test01();
test02();
return 0;
}
4.5 字符串比较
#include<iostream>
using namespace std;
void test01()
{
string str1 = "hello";
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();
return 0;
}
4.6 字符存取
#include<iostream>
using namespace std;
void test01()
{
string str1 = "hello";
// 通过 [] 访问单个字符
for (int i = 0; i < str1.size(); i++)
{
cout << str1[i] << " ";
}
cout << endl;
//通过at方式访问单个字符
for (int i = 0; i < str1.size(); i++)
{
cout << str1.at(i) << " ";
}
cout << endl;
//修改单个字符
str1[0] = 'x';
cout << str1 << endl;
str1.at(1) = 'x';
cout << str1 << endl;
}
int main()
{
test01();
return 0;
}
4.7 字符串的插入和删除
#include<iostream>
using namespace std;
void test01()
{
string str = "hello";
//插入
str.insert(1, "123");// h123ello
cout << str << endl;
//删除
str.erase(1, 3);
cout << str << endl;// hello
}
int main()
{
test01();
return 0;
}
4.8 子串获取
string substr(int pos = 0, int n = npos) const;//返回由pos开始的n个字符组成的字符串
#include<iostream>
using namespace std;
void test01()
{
string str = "abcdef";
string subStr = str.substr(1, 3);
cout << subStr << endl;// bcd
}
// 实用操作
void test02()
{
string email = "hello@sina.com";
// 从邮件地址中 获取用户信息
int pos = email.find("@");
string username = email.substr(0, pos);
cout << username << endl;
}
int main()
{
test02();
return 0;
}
5 vector容器
5.1 构造函数
1、vector是单端数组,可以动态扩展
2、动态扩展并不是在原空间之后接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
3、vector容器的迭代器是支持随机访问的迭代器
#include<iostream>
using namespace std;
#include <vector>
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);
vector<int>v3(10, 100);// 10 个100
printVector(v3);
vector<int>v4(v3);
printVector(v4);
}
int main()
{
test01();
return 0;
}
5.2 赋值操作
#include<iostream>
using namespace std;
#include <vector>
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;
v2 = v1;
printVector(v2);
vector<int>v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
vector<int>v4;
v4.assign(10,100);//赋值行为
printVector(v4);
}
int main()
{
test01();
return 0;
}
5.3 容量和大小
#include<iostream>
using namespace std;
#include <vector>
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的容量为:"<< v1.capacity() << endl;
cout << "v1的大小为:" << v1.size() << endl;
}
// 重新指定大小
v1.resize(15);
printVector(v1);// 默认填充 0
v1.resize(17, 100);
printVector(v1);// 填充100
v1.resize(8);
printVector(v1);// 删除后面的
}
int main()
{
test01();
return 0;
}
5.4 插入和删除
#include<iostream>
using namespace std;
#include <vector>
/*
push_back(ele); //尾部插入元素ele
pop_back( ); //删除最后一个元素
insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
insert(const_iterator pos, int count,ele); //迭代器指向位置pos插入count个元素
erase(const_iterator pos); //删除迭代器指向的元素
erase(const_iterator start,const_iterator end); //删除迭代器从start到end之间的元素
clear(); //删除容器中所有元素
*/
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);
}
//尾删
v1.pop_back();
printVector(v1);
//插入 第一个参数是迭代器
v1.insert(v1.begin(), 100);
printVector(v1);
v1.insert(v1.begin(), 3, 100);//在首部插入3个100
printVector(v1);
//删除
v1.erase(v1.begin());
printVector(v1);
v1.erase(v1.begin(),v1.end());
printVector(v1);
//清空
v1.clear();
}
int main()
{
test01();
return 0;
}
5.5 数据存取
#include<iostream>
using namespace std;
#include <vector>
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);
}
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
//获取第一个元素
cout << v1.front() << endl;
//获取最后一个元素
cout << v1.back() << endl;
}
int main()
{
test01();
return 0;
}
5.6 互换容器
实现两个容器内元素进行互换 swap(vec)
#include<iostream>
using namespace std;
#include <vector>
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;
for (int i = 10; i >0; i--)
{
v2.push_back(i);
}
printVector(v2);
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
//实际用途 巧用swap可以收缩内存空间
void test02()
{
vector<int>v;
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<int>(v).swap(v);//vector<int>(v)匿名对象,swap指针调换
cout << "v的容量:" << v.capacity() << endl;
cout << "v的大小:" << v.size() << endl;
}
int main()
{
test02();
return 0;
}
5.7 预留空间
减少vector在动态扩展容量时扩展次数
reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问
#include<iostream>
using namespace std;
#include <vector>
void test01()
{
vector<int>v;
//利用reserve预留空间
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();
return 0;
}
6 deque容器
6.1 构造函数
双端数组,可以对头端进行插入删除操作
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
#include <iostream>
using namespace std;
#include<deque>
void printDeque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
//*it=100;容器中的数据不可以修改了
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, 100);
printDeque(d3);
deque<int>d4(d3);
printDeque(d4);
}
int main()
{
test01();
return 0;
}
6.2 赋值操作
6.3 大小操作
6.4 插入和删除
6.5 数据存取
#include <iostream>
using namespace std;
#include<deque>
void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
//*it=100;容器中的数据不可以修改了
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(100);
d.push_front(200);
printDeque(d);
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();
return 0;
}
6.6 排序操作
对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
#include <iostream>
using namespace std;
#include<deque>
#include<algorithm>
void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
//*it=100;容器中的数据不可以修改了
cout << *it << " ";
}
cout << endl;
}
void test01()
{
deque<int>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(d.begin(), d.end());
printDeque(d);
}
int main()
{
test01();
return 0;
}
6.7 案例-评委打分
#include <iostream>
using namespace std;
#include<deque>
#include<vector>
#include<algorithm>
class Person
{
public:
Person(string n,int c)
{
name = n;
score = c;
}
string name;
int 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<int>d;
for (int i = 0; i < 10; i++)
{
int score = rand() % 41 + 60;
d.push_back(score);
}
//排序
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).score = avg;
it->score = avg;
}
}
void showScore(vector<Person>&v)
{
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
//cout << "姓名: " << (*it).name << " 平均分: " << (*it).score << endl;
cout << "姓名: " << it->name << " 平均分: " << it->score << endl;
}
}
int main()
{
vector<Person>v;//存放选手容器
createPerson(v);
setScore(v);
showScore(v);
return 0;
}
7 stack容器
先进后出,不可遍历
#include<iostream>
#include<stack>
using namespace std;
void test01()
{
stack<int>s;
s.push(10);
s.push(20);
s.push(30);
s.push(40);
s.push(50);
while (!s.empty())
{
cout << s.top() << endl;
s.pop();
}
cout << s.size();
}
int main()
{
test01();
return 0;
}
8 queue 容器
queue是一种先进先出的数据结构,只有队头队尾才可以被外界使用,因此队列也不允许遍历行为
#include<iostream>
#include<queue>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string n, int a)
{
name = n;
age = a;
}
};
void test01()
{
queue<Person>q;
Person p1("孙悟空", 999);
Person p2("猪八戒", 800);
Person p3("唐僧", 40);
Person p4("沙僧", 888);
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
cout << q.size();
while (!q.empty())
{
cout << q.front().name <<q.front().age<< endl;
cout << q.back().name << q.back().age << endl;
q.pop();
}
cout << q.size();
}
int main()
{
test01();
return 0;
}
9 list容器
9.1 基本概念
1、链表的组成:链表由一系列结点组成
2、结点的组成:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域
3、STL中的链表是一个双向循环列表
4、由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
5、list的优点:
·采用动态存储分配,不会造成内存浪费和溢出
·链表执行插入和删除操作十分方便,修改指针即可,不需要移动大星元素6、list的缺点:
·链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大
List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。
9.2 构造函数
#include <iostream>
using namespace std;
#include<list>
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);//遍历容器
//区间构造
list<int>L2(L1.begin(), L1.end());
printList(L2);
//拷贝构造
list<int>L3(L2);
printList(L3);
//n个elem
list<int>L4(10, 1000);
printList(L4);
}
int main()
{
test01();
return 0;
}
9.3 赋值和交换
#include <iostream>
using namespace std;
#include<list>
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);//遍历容器
list<int>L2;
L2 = L1;//=赋值
printList(L2);
list<int>L3;
L3.assign(L2.begin(), L2.end());
printList(L3);
list<int>L4;
L4.assign(10, 100);
printList(L4);
}
void test02()//交换
{
list<int>L1;
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(10, 100);
cout << "交换前:" << endl;
printList(L1);
printList(L2);
cout << "交换后:" << endl;
L1.swap(L2);
printList(L1);
printList(L2);
}
int main()
{
test02();
return 0;
}
9.4 大小操作
#include <iostream>
using namespace std;
#include<list>
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);//遍历容器
//判断空
if (L1.empty())
{
cout << "L1为空" << endl;
}
else
{
cout << "L1不为空" << endl;
cout << "L1的元素个数:" << L1.size() << endl;
}
//重新指定大小
L1.resize(10);
printList(L1);
L1.resize(12,100);
printList(L1);
L1.resize(2);
printList(L1);
}
int main()
{
test01();
return 0;
}
9.5 插入和删除
#include <iostream>
using namespace std;
#include<list>
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>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 插入200 1000 100 10 20
list<int>::iterator it = L.begin();
L.insert(++it, 1000);
printList(L);
//删除1000 100 10 20
it = L.begin();
L.erase(it);
printList(L);
//移除
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
printList(L);
L.remove(10000);
printList(L);
}
int main()
{
test01();
return 0;
}
9.6 数据存取
不能用 [ ] 和 at 访问list容器中的元素,list本质是链表,不是连续线性空间存储数据,迭代器也是不支持随机访问的。
#include <iostream>
using namespace std;
#include<list>
void test01()
{
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
L.push_back(40);
cout << "第一个元素为:" << L.front();
cout << "第二个元素为:" << L.back();
list<int>::iterator it = L.begin();
it++;
it--;//支持双向
//it=it+1;错误,不支持随机访问
}
int main()
{
test01();
return 0;
}
9.7 反转和排序
#include <iostream>
using namespace std;
#include<list>
void printList(const list<int>& L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool myCompare(int v1,int v2)
{
//降序,就让第一个数大于第二个数
return v1 > v2;
}
void test01()
{
list<int>L;
//尾插
L.push_back(10);
L.push_back(30);
L.push_back(70);
L.push_back(20);
L.push_back(50);
cout << "反转前:" << endl;
printList(L);
cout << "反转后:" << endl;
L.reverse();
printList(L);
//排序
//所有不支持随机访问迭代器的容器,不可以用标准算法sort(L.begin(),L.end());是错的
//不支持随机访问迭代器的容器,内部会提供一些算法
cout << "排序后:" << endl;
L.sort();//默认从小到大,升序
printList(L);
L.sort(myCompare);
printList(L);
}
int main()
{
test01();
return 0;
}
9.8 list容器排序案例
将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
排序规则:年龄升序,若年龄相同则按照身高进行降序
#include <iostream>
using namespace std;
#include<list>
class Person
{
public:
string m_Name;
int m_Age;
int m_Height;
Person(string name,int age,int height)
{
m_Name = name;
m_Age = age;
m_Height = height;
}
};
void printList(list<Person>& L)
{
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << " 身高:" << it->m_Height << endl;
}
}
bool comparePerson(Person& p1, Person& p2)
{
//年龄升序
if (p1.m_Age == p2.m_Age)
{
//年龄相同,身高降序
return p1.m_Height > p2.m_Height;
}
else
{
return p1.m_Age < p2.m_Age;
}
}
void test01()
{
list<Person>L;
Person p1("刘备", 32, 175);
Person p2("张飞", 35, 180);
Person p3("关羽", 40, 190);
Person p4("赵云", 35, 160);
Person p5("曹操", 35, 170);
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
printList(L);
cout << "-----------------------------------" << endl;
cout << "排序后:" << endl;
L.sort(comparePerson);
printList(L);
}
int main()
{
test01();
return 0;
}
10 set/multiset容器
所有元素都会在插入时自动被排序,属于关联式容器,底层结构是用二叉树实现
set不允许容器中有重复的元素
multiset允许容器中有重复的元素
10.1 构造和赋值
#include<iostream>
using namespace std;
#include<set>
void printSet(set<int>&s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;//没有push操作,只有insert方式
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
s1.insert(30);
//遍历
//set容器特点:所有元素在插入的时候会自动被排序
//不允许插入重复值
printSet(s1);
set<int>s2(s1);//拷贝构造
printSet(s2);
//赋值
set<int>s3;
s3 = s2;
printSet(s3);
}
int main()
{
test01();
return 0;
}
10.2 大小和交换
#include<iostream>
using namespace std;
#include<set>
void printSet(set<int>& s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;//没有push操作,只有insert方式
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
if (s1.empty())
{
cout << "s1为空" << endl;
}
else
{
cout << "s1不为空" << endl;
cout << "元素个数:" << s1.size() << endl;
}
//交换
set<int>s2;
s2.insert(100);
s2.insert(200);
s2.insert(300);
s2.insert(400);
cout << "交换前:" << endl;
printSet(s1);
printSet(s2);
s1.swap(s2);
cout << "交换后:" << endl;
printSet(s1);
printSet(s2);
}
int main()
{
test01();
return 0;
}
10.3 插入和删除
#include<iostream>
using namespace std;
#include<set>
void printSet(set<int>& s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
void test01()
{
set<int>s1;//没有push操作,只有insert方式
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(10);
printSet(s1);
//删除
s1.erase(s1.begin());//删除了10
printSet(s1);
//删除某个具体的值
s1.erase(30);
printSet(s1);
//清空
s1.erase(s1.begin(), s1.end());
printSet(s1);
s1.clear();
printSet(s1);
}
int main()
{
test01();
return 0;
}
10.4 查找和统计
#include<iostream>
using namespace std;
#include<set>
void test01()
{
set<int>s1;//没有push操作,只有insert方式
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(10);
printSet(s1);
set<int>::iterator pos = s1.find(30);
if (pos != s1.end())
{
cout << "找到元素:" << *pos << endl;
}
else
{
cout << "没有找到" << endl;
}
//统计30的个数
int num = s1.count(30);
//对于set而言,统计的结果要么是0要么是1
cout << "num = " << num << endl;
}
int main()
{
test01();
return 0;
}
10.5 set和multiset区别
#include<iostream>
using namespace std;
#include<set>
void test01()
{
set<int>s1;
pair<set<int>::iterator, bool> ret = s1.insert(10);
if (ret.second)
{
cout << "第一次插入成功" << endl;
}
else
{
cout << "第一次插入失败" << endl;
}
ret = s1.insert(10);
if (ret.second)
{
cout << "第二次插入成功" << endl;
}
else
{
cout << "第二次插入失败" << endl;
}
multiset<int>ms;
ms.insert(10);
ms.insert(10);
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
int main()
{
test01();
return 0;
}
10.6 pair对组创建使用
#include<iostream>
using namespace std;
void test01()
{
pair<string, int>p("Tom",18);
cout << "姓名:" << p.first << " 年龄:" << p.second << endl;
pair<string, int>p2 = make_pair("Jerry", 20);
cout << "姓名:" << p2.first << " 年龄:" << p2.second << endl;
}
int main()
{
test01();
return 0;
}
10.7 内置类型指定排序规则
#include <iostream>
using namespace std;
#include<set>
void printSet(set<int>& s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
class myCompare
{
public:
bool operator()(int v1,int v2)const
{
return v1 > v2;
}
};
void test01()
{
set<int>s1;
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(50);
s1.insert(40);
printSet(s1);
//指定排序规则为从大到小
set<int, myCompare>s2;
s2.insert(10);
s2.insert(30);
s2.insert(20);
s2.insert(50);
s2.insert(40);
for (set<int,myCompare>::iterator it = s2.begin(); it != s2.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
int main()
{
test01();
return 0;
}
10.8 自定义数据类型指定排序规则
#include <iostream>
using namespace std;
#include<set>
class Person
{
public:
string name;
int age;
Person(string n, int a)
{
name = n;
age = a;
}
};
class comparePerson
{
public:
bool operator()(const Person &p1, const Person &p2)const
{
return p1.age > p2.age;
}
};
void test01()
{
//自定义数据类型 都会指定排序规则
set<Person, comparePerson>s;
Person p1("刘备", 24);
Person p2("关羽", 32);
Person p3("张飞", 35);
Person p4("赵云", 37);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set<Person,comparePerson>::iterator it = s.begin(); it != s.end(); it++)
{
cout << "姓名:" << it->name << " 年龄:" << it->age << endl;
}
cout << endl;
}
int main()
{
test01();
return 0;
}
11 map/multimap容器
1、map中所有元素都是pair
2、pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
3、所有元素都会根据元素键值自动排序
4、本质:属于关联式容器,底层结构是用二叉树实现
5、优点:可以根据键值快速找到value值
6、map中不允许容器中有重复key值元素,multimap允许容器中有重复key值元素
11.1 构造和赋值
#include<iostream>
using namespace std;
#include<map>
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>(2, 20));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(4, 40));
printMap(m);
map<int, int>m2(m);//拷贝构造
printMap(m2);
map<int, int>m3;
m3 = m;
printMap(m3);
}
int main()
{
test01();
return 0;
}
11.2 大小和交换
#include<iostream>
using namespace std;
#include<map>
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>(2, 20));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(4, 40));
if (m.empty())
{
cout << "m为空" << endl;
}
else
{
cout << "m不为空" << endl;
cout << "m的大小为:" << m.size() << endl;
}
//交换
map<int, int>m2;
m.insert(pair<int, int>(5, 100));
m.insert(pair<int, int>(6, 200));
m.insert(pair<int, int>(7, 300));
m.insert(pair<int, int>(8, 400));
cout << "交换前:" << endl;
printMap(m);
printMap(m2);
cout << "交换后:" << endl;
m.swap(m2);
printMap(m);
printMap(m2);
}
int main()
{
test01();
return 0;
}
11.3 插入和删除
#include<iostream>
using namespace std;
#include<map>
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(make_pair(2, 20));
m.insert(map<int, int>::value_type(3, 30));
m[4] = 40;
//cout << m[5] << endl;// []不建议插入,可以利用key访问value
//确定key存在,找到value值
printMap(m);
//删除
m.erase(m.begin());
printMap(m);
m.erase(3);//只按照key删除
printMap(m);
m.erase(m.begin(), m.end());//区间删
printMap(m);
m.clear();
printMap(m);
}
int main()
{
test01();
return 0;
}
11.4 查找和统计
#include<iostream>
using namespace std;
#include<map>
void test01()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(make_pair(2, 20));
m.insert(map<int, int>::value_type(3, 30));
m.insert(make_pair(3, 40));
map<int, int>::iterator pos = m.find(3);
if (pos != m.end())
{
cout << "查找到了元素 key = " << (*pos).first << " value = " << (*pos).second << endl;
}
else
{
cout << "未找到" << endl;
}
//统计
int num = m.count(3);//num只能为0,1
cout << "num = " << num << endl;
}
int main()
{
test01();
return 0;
}
11.5 排序
#include<iostream>
using namespace std;
#include<map>
class myCompare
{
public:
bool operator()(int v1,int v2)const
{
return v1 > v2;//仿函数
}
};
void test01()
{
map<int, int, myCompare>m;
m.insert(pair<int, int>(1, 10));
m.insert(make_pair(2, 20));
m.insert(map<int, int>::value_type(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
for (map<int, int, myCompare>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << (*it).first << " value = " << it->second << endl;
}
cout << endl;
}
int main()
{
test01();
return 0;
}
12 STL案例—员工分工
#include<iostream>
using namespace std;
#include<map>
#include<vector>
#include<ctime>
#include<string>
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
class Worker
{
public:
string name;
int salary;
};
void createWorker(vector<Worker>&v)
{
string nameSeed = "ABCDEFGHIJ";
for (int i = 0; i < 10; i++)
{
Worker worker;
worker.name = "员工";
worker.name += nameSeed[i];
worker.salary = rand() % 10000 + 10001;//10000~20000
v.push_back(worker);//将员工放入容器中
}
}
void setGroup(vector<Worker>& v, multimap<int, Worker>& m)
{
for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++)
{
//产生随机部门编号
int deptId = rand() % 3;//0 1 2
//将员工插入到分组中
m.insert(make_pair(deptId, *it));
}
}
void showWorkerByGroup(multimap<int, Worker>& m)
{
cout << "策划部门:" << endl;
multimap<int,Worker>::iterator pos = m.find(CEHUA);
int count = m.count(CEHUA);
int index = 0;
for (; pos != m.end() && index < count; index++, pos++)
{
cout << "姓名:" << pos->second.name << " 工资:" << pos->second.salary << endl;
}
cout << "---------------------------------------" << endl;
cout << "研发部门:" << endl;
pos = m.find(YANFA);
count = m.count(YANFA);
index = 0;
for (; pos != m.end() && index < count; index++, pos++)
{
cout << "姓名:" << pos->second.name << " 工资:" << pos->second.salary << endl;
}
cout << "---------------------------------------" << endl;
cout << "美术部门:" << endl;
pos = m.find(MEISHU);
count = m.count(MEISHU);
index = 0;
for (; pos != m.end() && index < count; index++, pos++)
{
cout << "姓名:" << pos->second.name << " 工资:" << pos->second.salary << endl;
}
}
int main()
{
srand((unsigned int)time(NULL));//随机数种子
//创建员工
vector<Worker>vWorker;
createWorker(vWorker);
//测试
/*for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++)
{
cout << "姓名:" << it->name << " 工资:" << it->salary << endl;
}*/
//分组
multimap<int, Worker>mWorker;
setGroup(vWorker,mWorker);
//分组显示员工
showWorkerByGroup(mWorker);
return 0;
}
13 函数对象—函数对象基本使用
函数对象概念:
重载函数调用操作符的类,其对象常称为函数对象
函数对象使用重载的()时,行为类似函数调用,也叫仿函数本质:函数对象(仿函数)是一个类,不是一个函数
函数对象的使用:
函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值;
函数对象超出普通函数的概念,函数对象可以有自己的状态;
函数对象可以作为参数传递;
#include<iostream>
using namespace std;
//1、可以像普通函数那样调用,可以有参数,可以有返回值;
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test01()
{
MyAdd myAdd;
cout << myAdd(10, 10);
}
//2、超出普通函数的概念,函数对象可以有自己的状态;
class MyPrint
{
public:
MyPrint()
{
this->count = 0;
}
void operator()(string test)
{
cout << test << endl;
this->count++;
}
int count;//内部自己的状态
};
void test02()
{
MyPrint myPrint;
myPrint("hello world");
myPrint("hello world");
myPrint("hello world");
myPrint("hello world");
cout << "MyPrint调用次数为:" << myPrint.count << endl;
}
//3、函数对象可以作为参数传递;
void doPrint(MyPrint& mp, string test)
{
mp(test);
}
void test03()
{
MyPrint myPrint;
doPrint(myPrint, "Hello c++!");
}
int main()
{
test03();
return 0;
}
14 谓词
返回bool类型的仿函数称为谓词
如果operator()接受一个参数,那么叫做一元谓词如果operator()接受两个参数,那么叫做二元谓词
14.1 一元谓词
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
class GreaterFive
{
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的数字
// GreaterFive()匿名对象
vector<int>::iterator it;
it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end())
{
cout << "未找到" << endl;
}
else
{
cout << "找到了大于5的数字 " << endl;
cout << *it << endl;
}
}
int main()
{
test01();
return 0;
}
14.2 二元谓词
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
class MyCompare
{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(40);
v.push_back(50);
v.push_back(30);
v.push_back(30);
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();
return 0;
}
15 内建函数对象
STL内建了一些函数对象
#include<functional>
15.1 算术仿函数
实现四则运算,其中negate是一元运算,其他都是二元运算
#include<iostream>
using namespace std;
#include<functional>
void test01()
{
// negate 取反
negate<int>n;
cout << n(20) << endl;
plus<int>p;
cout << p(1, 1) << endl;
}
int main()
{
test01();
return 0;
}
15.2 关系仿函数
#include<iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(30);
v.push_back(50);
v.push_back(40);
v.push_back(20);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
sort(v.begin(), v.end(), greater<int>());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
int main()
{
test01();
return 0;
}
15.3 逻辑仿函数
#include<iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
void test01()
{
vector<bool>v;
v.push_back(true);
v.push_back(false);
v.push_back(true);
v.push_back(true);
v.push_back(false);
for (vector<bool>::iterator it = v.begin(); it != v.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
//利用逻辑非,将容器v搬运到容器v2中,并且执行取反
vector<bool>v2;
v2.resize(v.size());
//搬运
transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());
for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}
int main()
{
test01();
return 0;
}
16 常用遍历算法
16.1 for_each
for_each(iterator beg, iterator_end,_func);
起始迭代器,结束迭代器,函数(普通函数,仿函数)
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void print01(int val)
{
cout << val << " ";
}
class print02
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int>v;
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();
return 0;
}
16.2 transform
搬运容器到另一个容器
transform(iterator beg, iterator_end, iterator beg2, _func);
源容器起始迭代器,源容器结束迭代器,目标容器起始迭代器,函数(普通函数,仿函数)
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
class Transform
{
public:
int operator()(int v)
{
return v + 100;
}
};
class print01
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>vTarget;
vTarget.resize(v.size());
transform(v.begin(), v.end(), vTarget.begin(), Transform());
for_each(vTarget.begin(), vTarget.end(), print01());
}
int main()
{
test01();
return 0;
}
17 常用查找算法
17.1 find
find(iterator beg, iterator_end, value);
起始迭代器,结束迭代器,查找的元素
返回迭代器
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
//查找 内置数据类型
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//查找容器中是否有 5
vector<int>::iterator it = find(v.begin(), v.end(), 5);
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了" << *it << endl;
}
}
//查找 自定义数据类型
class Person
{
public:
string name;
int age;
Person(string n, int a)
{
name = n;
age = a;
}
//重载 == 让底层find知道如何对比Person类型
bool operator==(const Person& p)
{
if (this->name == p.name && this->age == p.age)
{
return true;
}
else
return false;
}
};
void test02()
{
vector<Person>v;
Person p1("aaa", 12);
Person p2("bbb", 23);
Person p3("ccc", 34);
Person p4("ddd", 45);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
Person pp("bbb", 23);
vector<Person>::iterator it = find(v.begin(), v.end(), pp);
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了" << "姓名:" << it->name << " 年龄:" << it->age << endl;
}
}
int main()
{
test02();
return 0;
}
17.2 find_if
find(iterator beg, iterator_end, _Pred);
起始迭加器,结束迭加器,_Pred函数或者谓词(返回bool类型的仿函数)
返回迭代器
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
//查找 内置数据类型
class GreaterFive
{
public:
bool operator()(int v)
{
return v > 5;
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了大于5的数字:" << *it << endl;
}
}
//查找 自定义数据类型
class Person
{
public:
string name;
int age;
Person(string n, int a)
{
name = n;
age = a;
}
};
class Greater20
{
public:
bool operator()(Person& p)
{
return p.age > 30;
}
};
void test02()
{
vector<Person>v;
Person p1("aaa", 12);
Person p2("bbb", 23);
Person p3("ccc", 34);
Person p4("ddd", 45);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
Person pp("bbb", 23);
vector<Person>::iterator it = find_if(v.begin(), v.end(), Greater20());
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了年龄大于30的人:" << "姓名:" << it->name << " 年龄:" << it->age << endl;
}
}
int main()
{
test02();
return 0;
}
17.3 adjacent_find
adjacent_find(iterator beg, iterator_end);
查找相邻重复元素,返回相邻元素的第一个位置的迭代器
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void test01()
{
vector<int>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(4);
v.push_back(3);
v.push_back(3);
vector<int>::iterator it = adjacent_find(v.begin(), v.end());
if (it == v.end())
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了相邻重复元素:" << *it << endl;//4
}
}
int main()
{
test01();
return 0;
}
17.4 binary_search
bool binary_search(iterator beg, iterator_end, value);
查找指定的元素,查找到返回true,否则返回false
在无序序列中不可用
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);//必须是有序升序数列
}
//v.push_back(2);无序则结果未知
bool ret = binary_search(v.begin(), v.end(),9);
if (!ret)
{
cout << "没有找到" << endl;
}
else
{
cout << "找到了9元素" << endl;
}
}
int main()
{
test01();
return 0;
}
17.5 count
count(iterator beg, iterator_end, value);
统计元素出现次数,返回int类型数据,value统计的元素
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
//查找 内置数据类型
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(40);
v.push_back(30);
v.push_back(10);
int num = count(v.begin(), v.end(), 10);
cout << "10的个数为:" << num << endl;
}
//查找 自定义数据类型
class Person
{
public:
string name;
int age;
Person(string n, int a)
{
name = n;
age = a;
}
//重载 ==
bool operator==(const Person& p)
{
if (this->age== p.age)
{
return true;
}
else
return false;
}
};
void test02()
{
vector<Person>v;
Person p1("aaa", 12);
Person p2("bbb", 13);
Person p3("ccc", 13);
Person p4("ddd", 45);
Person p5("eee", 45);
Person p6("fff", 45);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
v.push_back(p6);
Person pp("ggg", 45);
int num = count(v.begin(), v.end(), pp);
cout << "和pp同岁的人有:" << num << " 个" << endl;
}
int main()
{
test02();
return 0;
}
17.6 count_if
count_if(iterator beg, iterator_end, _Pred);按条件统计元素个数
返回 int
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
//查找 内置数据类型
class Greater20
{
public:
bool operator()(int val)
{
return val > 20;
}
};
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(40);
v.push_back(30);
v.push_back(50);
int num = count_if(v.begin(), v.end(), Greater20());
cout << "大于20的元素个数为:" << num << endl;
}
//查找 自定义数据类型
class Person
{
public:
string name;
int age;
Person(string n, int a)
{
name = n;
age = a;
}
};
class AgeGreater20
{
public:
bool operator()(const Person& p)
{
return p.age > 20;
}
};
void test02()
{
vector<Person>v;
Person p1("aaa", 12);
Person p2("bbb", 13);
Person p3("ccc", 13);
Person p4("ddd", 24);
Person p5("eee", 40);
Person p6("fff", 45);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
v.push_back(p6);
int num = count_if(v.begin(), v.end(), AgeGreater20());
cout << "统计年龄大于20的个数为:" << num << " 个" << endl;
}
int main()
{
test02();
return 0;
}
18 常用排序算法
18.1 sort
sort(iterator beg, iterator_end, _Pred);
如果不填_Pred则默认从小到大排序,写了就按照所写方法排序
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<functional>
class Greater20
{
public:
bool operator()(int val)
{
return val > 20;
}
};
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(40);
v.push_back(30);
v.push_back(50);
//默认升序
sort(v.begin(), v.end());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
//降序
sort(v.begin(), v.end(), greater<int>());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
18.2 random_shuffle
random_shuffle(iterator beg, iterator_end);
指定范围内的元素随机调整次序
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<functional>
#include<ctime>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
srand((unsigned int)time(NULL));//随机种子
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
//默认
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();
return 0;
}
18.3 merge
将两个容器元素合并,并存储到另一容器中
merge(iterator beg1, iterator_end1, iterator beg2, iterator_end2, iterator dest beg);
两个容器必须是有序的;
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
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>v2;
v2.push_back(1);
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
v2.push_back(60);
vector<int>vTarget;
//提前给目标容器分配空间
vTarget.resize(v.size() + v2.size());
merge(v.begin(), v.end(),v2.begin(),v2.end(),vTarget.begin());
for_each(vTarget.begin(), vTarget.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
18.4 reverse
reverse(iterator beg, iterator_end);
反转指定范围元素
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector<int>v;
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(50);
v.push_back(40);
for_each(v.begin(), v.end(), myPrint);
cout << endl;
reverse(v.begin(), v.end());
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
19 常用拷贝和替换算法
19.1 copy
copy(iterator beg, iterator_end, iterator dest beg);
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>v2;
v2.resize(v.size());
copy(v.begin(), v.end(), v2.begin());
for_each(v2.begin(), v2.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
19.2 replace
replace(iterator beg, iterator_end, old value, new value);
将区间内的所有旧元素替换为新元素
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), myPrint);
cout << endl;
replace(v.begin(), v.end(), 2, 1);
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
19.3 replace_if
replace_if(iterator beg, iterator_end, _Pred, new value);按条件替换
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<functional>
void myPrint(int val)
{
cout << val << " ";
}
class GreaterFive
{
public:
bool operator()(int val)
{
return val > 5;
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), myPrint);
cout << endl;
//大于5的都替换为100
replace_if(v.begin(), v.end(), GreaterFive(), 100);
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
19.4 swap
swap(container c1, container c2);
互换两个容器元素
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<functional>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector<int>v;
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
v1.push_back(i + 100);
}
for_each(v.begin(), v.end(), myPrint);
cout << endl;
for_each(v1.begin(), v1.end(), myPrint);
cout << endl;
cout << "交换后:" << endl;
swap(v, v1);
for_each(v.begin(), v.end(), myPrint);
cout << endl;
for_each(v1.begin(), v1.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
20 常用算术生成算法
20.1 accumulate
accumulate(iterator beg, iterator_end,value);
计算区间容器元素累积总和,value为起始值
#include<iostream>
using namespace std;
#include<vector>
#include<numeric>
#include<algorithm>
void test01()
{
vector<int>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();
return 0;
}
20.2 fill
fill(iterator beg, iterator_end,value);将指定区间填充元素
#include<iostream>
using namespace std;
#include<vector>
#include<numeric>
#include<algorithm>
void myPrint(int val)
{
cout << val << " ";
}
void test01()
{
vector<int>v;
v.resize(10);
fill(v.begin(), v.end(), 10);
for_each(v.begin(), v.end(), myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
21 常用集合算法
21.1 set_intersection
set_intersection(iterator beg1, iterator_end1, iterator beg2, iterator_end2, iterator dest beg)
求两个容器交集,返回交集最后一个迭代器
两个集合必须为有序序列
#include<iostream>
using namespace std;
#include<vector>
#include<numeric>
#include<algorithm>
void myPrint(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>vTarget;
vTarget.resize(min(v1.size(), v2.size()));
vector<int>::iterator itFind = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), itFind, myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
21.2 set_union
set_union(iterator beg1, iterator_end1, iterator beg2, iterator_end2, iterator dest beg)
求两个容器并集,返回并集最后一个迭代器
两个集合必须为有序序列
#include<iostream>
using namespace std;
#include<vector>
#include<numeric>
#include<algorithm>
void myPrint(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>vTarget;
vTarget.resize(v1.size() + v2.size());
vector<int>::iterator itFind = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), itFind, myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}
21.3 set_difference
set_difference(iterator beg1, iterator_end1, iterator beg2, iterator_end2, iterator dest beg)
求两个容器差集,返回差集最后一个迭代器
两个集合必须为有序序列
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void myPrint(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>vTarget;
//最特殊情况,两个容器没有交集 取两个容器中大的作为容器开辟空间
vTarget.resize(max(v1.size(), v2.size()));
cout << "v1和v2的差集为:" << endl;
vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), itEnd, myPrint);
cout << endl;
cout << "v2和v1的差集为:" << endl;
itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget.begin());
for_each(vTarget.begin(), itEnd, myPrint);
cout << endl;
}
int main()
{
test01();
return 0;
}