当前位置: 首页 > news >正文

【stl -- 常用算法】

目录:

  • 前言
  • 一、遍历算法
    • for_each、transform
  • 二、查找、统计算法
    • find、find_if
    • adjacent_find
    • binary_search
    • count、count_if
  • 三、排序算法
    • sort
    • random_shuffle
    • merge
    • reverse
  • 拷贝、替换算法
    • copy
    • replace、replace_if
    • swap
  • 算数生成算法
    • accumulate
    • fill
  • 集合算法
    • set_intersection
    • set_union
    • set_difference

前言

打怪升级:第19天
在这里插入图片描述

在学习这些算法是我们需要了解一些头文件:< algorithm > 、< numeric > 和 < functional >
< algorithm > 是stl头文件中最大的一个,包含下方介绍的绝大多数算法
< numeric > 体积很小,只包含几个在序列上进行简单数学运算模板函数
< functional >定义了一些模板类、用以声明函数对象。


一、遍历算法

在这里插入图片描述

for_each、transform

这里是引用

class Form
{
public:
	int operator()(int& v)
	{
		return v + 1000; //  这里我们可以进行各种操作
	}
}; 

void Print(int v)
{
	cout << v << ' ';
}

void test04()
{
	vector<int>v1;
	for (int i = 0; i < 8; ++i)
	{
		v1.push_back(i);
	}
	vector<int>v2;
	v2.resize(v1.size());   //  改变大小,空位默认用 0 填充
	// v2.reserve(v1.size());   reserve是预开辟空间,但是实际大小还是0,
	// 而我们使用transform时需要有足够的空间来存放搬运过来的数据, 因此这里不可以使用 

	transform(v1.begin(), v1.end(), v2.begin(), Form());  //  Form()  为仿函数、也可以直接使用函数
	for_each(v1.begin(), v1.end(), Print);  //  Print   为函数指针、也可以使用仿函数
	cout << endl;
	for_each(v2.begin(), v2.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述


二、查找、统计算法

在这里插入图片描述

find、find_if

在这里插入图片描述

class Greater
{
public:
	bool operator()(int val)  // 谓词就是用来做判断的
	{
		return val > 650;
	}
};

void Print(int val)
{
	cout << val << ' ';
}

void test05()
{
	vector<int>v;
	for (int i = 0; i < 10; ++i)
	{
		v.push_back(rand() % 100 + 600);
	}
	for_each(v.begin(), v.end(), Print);
	cout << endl;

	vector<int>::iterator it = find(v.begin(), v.end(), 600);  // 查找数字600
	if (it != v.end())
	{
		cout << *it << endl;
	}
	else
	{
		cout << "did not find" << endl;
	}

	it = find_if(v.begin(), v.end(), Greater()); //  查找有没有大于650的数字
	if (it != v.end())
	{
		cout << *it << endl;
	}
	else
	{
		cout << "did not find" << endl;
	}

}

运行实例:
在这里插入图片描述

find -> 自定义数据类型 – 示例:

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

	bool operator==(Person p)  // 重载==,告诉编译器查找的规则
	{
		if (this->name == p.name && this->age == p.age)
			return true;
		else
			return false;
	}
	string name;
	int age;
};

void test06()
{
	vector<Person>v1;
	Person p1("小米粒", 20);
	v1.push_back(p1);
	Person p2("陈暖树", 20);
	v1.push_back(p2);
	Person p3("裴钱", 22);
	v1.push_back(p3);
	Person p4("李宝瓶", 24);
	v1.push_back(p4);
	Person p5("李宝瓶", 24);

	vector<Person>::iterator it = find(v1.begin(), v1.end(), p5);
	if (it != v1.end())
	{
		cout << "name->" << it->name << " age->" << it->age << endl;
	}
	else
	{
		cout << "did not find" << endl;
	}
}

运行实例:
在这里插入图片描述


adjacent_find

在这里插入图片描述

void PrintVector(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(rand() % 3);
	}

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

	//  查找连续相同的第一组数据
	vector<int>::iterator vit = adjacent_find(v1.begin(), v1.end()); // 查v1容器
	if (vit != v1.end())
	{
		cout << "adjacent data is : " << *vit << endl;
	}
	else
	{
		cout << "did not find" << endl;
	}
	vit = adjacent_find(v2.begin(), v2.end());  // 查v2容器
	if (vit != v2.end())
	{
		cout << "adjacent data is : " << *vit << endl;
	}
	else
	{
		cout << "did not find" << endl;
	}
}

示例:在这里插入图片描述


binary_search

在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}

void test02()
{
	vector<int>v1;
	set<int>s1;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(rand() % 100);
		s1.insert(rand() % 100);
	}

	//  binary_search 必须在有序容器中进行查找
	sort(v1.begin(), v1.end(), greater<int>()); // 排降序
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	for_each(s1.begin(), s1.end(), Print);
	cout << endl;

	bool target = binary_search(v1.begin(), v1.end(), 30);
	if (target)
	{
		cout << "30存在" << endl;
	}
	else
	{
		cout << "30不存在" << endl;
	}
	target = binary_search(s1.begin(), s1.end(), 30);
	if (target)
	{
		cout << "30存在" << endl;
	}
	else
	{
		cout << "30不存在" << endl;
	}
}

示例:在这里插入图片描述


count、count_if

在这里插入图片描述
count 示例:

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

	bool operator==(const Person& p)
	{
		return this->m_name == p.m_name && this->m_age == p.m_age;
	}

	string m_name;
	int m_age;
};

void test01()
{
	vector<int>v1;
	for (int i = 0; i < 100; ++i)  //  100 个 0~9之间的数字
	{
		v1.push_back(rand() % 10);
	}
	
	/* bool found = binary_search(v1.begin(), v1.end(), 5); // 二分查找 只适用于 有序序列
	if (found)
	{
		cout << "find it" << endl;
	}
	else
	{
		cout << "did not find" << endl;
	}*/

	cout << "9 is count->" << count(v1.begin(), v1.end(), 9) << endl;  //  统计 9 的个数

	vector<Person>v2;
	Person p1("aaa", 19);
	v2.push_back(p1);
	Person p2("bbb", 12);
	v2.push_back(p2);
	Person p3("ccc", 14);
	v2.push_back(p3);
	Person p4("ddd", 16);
	v2.push_back(p4);
	Person p5("ccc", 14);
	v2.push_back(p5);

	Person tmp("ccc", 14);

	int found = count(v2.begin(), v2.end(), tmp); //对于自定义类型,需要重载== ,来告诉编译器相等的条件
	cout << "count elements thit match val-> " << found << endl;

}

运行实例:
在这里插入图片描述

三、排序算法

在这里插入图片描述

sort

顺序:默认排升序,使用非常广泛。在这里插入图片描述

void Print(int v)
{
	cout << v << ' ';
}

void test03()
{
	vector<int>v1;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(rand() % 100);
	}

	cout << "初始数据:";
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "升序排列:";
	sort(v1.begin(), v1.end());
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "降序排列:";
	sort(v1.begin(), v1.end(), greater<int>());  //  此处使用内建函数对象
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述

random_shuffle

洗牌:对区间内数据进行重新排列;
使用场景:抽签、随机取号等。
在这里插入图片描述

void Init(vector<int>&v, int val)
{
	for (int i = 0; i < 10; ++i)
	{
		v.push_back(i + val);
	}
}

void Print(int v)
{
	cout << v << ' ';
}

void test02()
{
	srand((unsigned int)time(NULL));
	
	vector<int>v1;
	Init(v1, 10);
	
	cout << "random_shuffle: ";
	random_shuffle(v1.begin(), v1.end());   //  洗牌1
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	
	cout << "random_shuffle: ";
	random_shuffle(v1.begin(), v1.end());   //  洗牌2
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	
	cout << "random_shuffle: ";
	random_shuffle(v1.begin(), v1.end());   //  洗牌3
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述


merge

合并:将两个有序容器中的数据进行合并,并把合并后的数据放到目标容器中,
这里需要注意:目标容器需要提前开辟好足够的空间。
在这里插入图片描述

void Print(int v)
{
	cout << v << ' ';
}

void test04()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 8; ++i)
	{
		v1.push_back(i);
		v2.push_back(i + 5);
	}
	cout << "v1-> ";
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	cout << "v2-> ";
	for_each(v2.begin(), v2.end(), Print);
	cout << endl;

	vector<int>vtarget; // 目标容器
	vtarget.resize(v1.size() + v2.size());
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vtarget.begin());
	cout << "vtarget-> ";
	for_each(vtarget.begin(), vtarget.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述


reverse

反转:reverse,将容器内的数据进行反转。
在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}

void test03()
{
	vector<int>v1;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(rand() % 10);
	}
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "反转: ";
	reverse(v1.begin(), v1.end());
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "排序: ";
	sort(v1.begin(), v1.end());
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "反转: ";
	reverse(v1.begin(), v1.end());  // 对有序数据进行反转,相当于排反序
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
}

运行实例:在这里插入图片描述


拷贝、替换算法

在这里插入图片描述

copy

示例:

void Print(int v)
{
	cout << v << ' ';
}

//  拷贝和替换函数
void test08()
{
	// copy
	vector<int>v1;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(i);
	}

	//vector<int>v2;
	//v2.resize(v1.size());  //  不要忘记分配大小
	 将v1容器完全拷贝到v2,其实如果只是这样的操作,不如直接使用拷贝构造或者赋值operator=
	//copy(v1.begin(), v1.end(), v2.begin());
	// vector<int>v2(v1);  或者   v2 = v1;
	

	 //  copy更常用的是:将一个容器到一部分内容进行拷贝

	cout << "v1: ";
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	//  将v1的前半部分数据拷贝到v2
	vector<int>v2;
	v2.resize(v1.size() / 2);
	copy(v1.begin(), v1.end() - v1.size() / 2, v2.begin());
	cout << "v2: ";
	for_each(v2.begin(), v2.end(), Print);
	cout << endl;

}

运行实例:
在这里插入图片描述


replace、replace_if

在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}
// 拷贝和替换算法
// replace
// replace_if

bool GreaterTow(int val)
{
	return val > 2;
}

void test01()
{
	vector<int>v1;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(rand() % 5);
	}
	vector<int>v2(v1);
	cout << "替换前:";
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	
	cout << "替换后:";
	replace(v1.begin(), v1.end(), 0, 1000);  //  将 0 全部替换成 1000
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "按条件替换:";
	replace_if(v2.begin(), v2.end(), GreaterTow, 2);  // 将 大于 2 的全部替换成 2
	for_each(v2.begin(), v2.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述


swap

在这里插入图片描述

bool GreaterTow(int val)
{
	return val > 2;
}

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

	cout << "交换前:" << endl;
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	for_each(v2.begin(), v2.end(), Print);
	cout << endl;
	cout << "v1: " << v1.size() << ' ' << v1.capacity() << endl;
	cout << "v2: " << v2.size() << ' ' << v2.capacity() << endl;

	cout << "交换后:" << endl;
	swap(v1, v2);  //  直接传两个容器
	               //  vector中也内置了swap函数模板,因此也可以写成: v1.swap(v2);
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
	for_each(v2.begin(), v2.end(), Print);
	cout << endl;
	cout << "v1: " << v1.size() << ' ' << v1.capacity() << endl;
	cout << "v2: " << v2.size() << ' ' << v2.capacity() << endl;
}

运行实例:
在这里插入图片描述


算数生成算法

在这里插入图片描述

accumulate

在这里插入图片描述

void test03()
{
	//  accumulate  -- 求和
	vector<int>v1;
	for (int i = 0; i <= 100; ++i)
	{
		v1.push_back(i);
	}
	//											0 为初始累加值
	int total = accumulate(v1.begin(), v1.end(), 0);
	cout <<  total << endl;

	

int cnt = accumulate(v1.begin(), v1.end(), 1000);
	cout << cnt << endl;

}

运行实例:
在这里插入图片描述


fill

在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}

void test05()
{
	// fill  -- 填充
	// 对于填充区间,我们既可以在使用 resize 扩大空间的同时设置填充数据,也可以后期使用 fill 更改填充数据

	vector<int>v1;
	cout << "申请空间,并初始化为100" << endl;
	v1.resize(10, 100); //  第二个参数默认为0,此时我们改为100
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;

	cout << "将后半部分的数值改为520" << endl;
	fill(v1.begin() + v1.size() / 2, v1.end(), 520);
	for_each(v1.begin(), v1.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述


集合算法

集合算法的 ‘集合’ 指的是两个容器里的数据需要是有序的,并非限制只有set容器的数据才可以使用。
注意:交集和并集:a与b的交集,a与b的交集,因此a与b和b与a结果都是一样的,
但是差集不一样,a相对于b的差集,和b相对于a的差集,可能会得到两个结果,下面我们通过实践来验证。
在这里插入图片描述

set_intersection

在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}

void test06()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(i);         //  0 ~ 9
		v2.push_back(i + 5);     //  5 ~ 14
	}

	vector<int>vTarget;
	vTarget.resize(min(v1.size(), v2.size()));  // 一个集合包含于另一个集合时size最大
	vector<int>::iterator intEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin()); 
	for_each(vTarget.begin(), intEnd, Print);   //  intEnd 不一定等于 end()
	cout << endl;
	for_each(vTarget.begin(), vTarget.end(), Print);
	cout << endl;
}

运行实例:在这里插入图片描述

set_union

在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}

void test07()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(i);         //  0 ~ 9
		v2.push_back(i + 5);     //  5 ~ 14
	}

	vector<int>vTarget;
	vTarget.resize(v1.size() + v2.size());  // 两个集合交集为空时最大
	vector<int>::iterator intEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	for_each(vTarget.begin(), intEnd, Print);
	cout << endl;
	for_each(vTarget.begin(), vTarget.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述

set_difference

注意:a相对b的差集、b相对于a的差集。
在这里插入图片描述

void Print(int val)
{
	cout << val << ' ';
}

void test08()
{
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10; ++i)
	{
		v1.push_back(i);         //  0 ~ 9
		v2.push_back(i + 5);     //  5 ~ 14
	}

	vector<int>vTarget1;
	cout << "v1 相对于 v2的差集:" << endl;
	vTarget1.resize(v1.size());  // 两个集合完全不同时最大			
	vector<int>::iterator intEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget1.begin());
	for_each(vTarget1.begin(), intEnd, Print);
	cout << endl;
	for_each(vTarget1.begin(), vTarget1.end(), Print);
	cout << endl;

	vector<int>vTarget2;
	cout << "v2 相对于 v1的差集:" << endl;
	vTarget2.resize(v2.size());  // 两个集合完全不同时最大			
	intEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget2.begin());
	for_each(vTarget2.begin(), intEnd, Print);
	cout << endl;
	for_each(vTarget2.begin(), vTarget2.end(), Print);
	cout << endl;
}

运行实例:
在这里插入图片描述


以上内容为看过黑马c++后的知识总结,如果有什么疑问或者建议都可以在评论区留言,感谢大家对在这里插入图片描述的支持。

相关文章:

  • python图像处理(图像缩放)
  • 电商项目之同一笔单多次收款成功
  • OpenFeign总结
  • 【Linux】基础IO --- 系统级文件接口、文件描述符表、文件控制块、fd分配规则、重定向…
  • 计算机网络01_---软考高级系统架构师010
  • 【Linux】冯诺依曼体系结构与操作系统概念理解
  • 【c语言进阶】枚举与联合体的基本知识大全
  • Python与Matlab混合编程案例
  • 排列的时候如何避免重复?
  • 芒果改进YOLOv5系列:原创结合Conv2Formers改进结构,Transformer 风格的卷积网络视觉基线模型,超越ConvNeXt结构
  • 利用Windows系统服务进行权限提升
  • WebAssembly编译之(2)-Ubuntu搭建WASM编译环境
  • InstanceNorm LayerNorm
  • yolo结构介绍
  • 最详细、最仔细、最清晰的几道python习题及答案(建议收藏哦)
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • HTTP请求重发
  • node.js
  • spring + angular 实现导出excel
  • Unix命令
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 离散点最小(凸)包围边界查找
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 正则表达式小结
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 进程与线程(三)——进程/线程间通信
  • (1)bark-ml
  • (3)llvm ir转换过程
  • (C++20) consteval立即函数
  • (八十八)VFL语言初步 - 实现布局
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 使用配置文件
  • .net 无限分类
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .NET是什么
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .pyc文件是什么?
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
  • [ 云计算 | AWS 实践 ] 基于 Amazon S3 协议搭建个人云存储服务
  • [ASP]青辰网络考试管理系统NES X3.5
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [BetterExplained]书写是为了更好的思考(转载)
  • [Bugku]密码???[writeup]
  • [BZOJ3757] 苹果树
  • [CareerCup] 2.1 Remove Duplicates from Unsorted List 移除无序链表中的重复项