STL-算法

STL-算法

STL的三大组件:容器(container) 算法(algorithm) 迭代器(iterator)

STL算法部分主要由头文件 <algorithm>,<numeric>,<functional> 组成。要使用 STL中的算法函数必须包含头文件 <algorithm>

查找统计算法

简述 算法名称 功能
统计 count 返回某个元素出现的次数
统计 count_if 返回某个元素(当函数或仿函数的返回值为true)出现的次数
查找 find 根据值查找某个元素
查找 find_if 查找某个元素(当函数或仿函数的返回值为true)
查找 search 查找一个序列出现的位置
查找 search_n 在范围中查找第一个连续n个元素都等价于给定值的子范围的位置
二分查找 binary_search 在有序序列中查找value,找到返回true

统计

std::count 计算一个范围内特定元素的出现次数。

std::vector<int> my_vector = {1, 2, 3, 3, 4, 3};  
int count = std::count(my_vector.begin(), my_vector.end(), 3);  
std::cout << "Count of element 3: " << count << std::endl;

查找

std::find:在一个范围内查找特定元素,返回指向该元素的迭代器。

#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
   std::vector<int> my_vector = {1, 2, 3, 4, 5};
   auto it = std::find(my_vector.begin(), my_vector.end(), 3);
   if (it != my_vector.end())
   {
      std::cout << "found  3 at position: " << std::distance(my_vector.begin(), it) << std::endl;
   }
   else
   {
      std::cout << "Element 3 not found" << std::endl;
   }

   return 0;
}
// found  3 at position: 2
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//查找内置数据类型
void test01()
{
    vector<int>v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    //返回一个迭代器,如果没有找到,返回end()
    vector<int>::iterator it = find(v.begin(), v.end(), 5);
    if (it == v.end())
        cout << "没找到" << endl;
    else
        cout << "找到了" << *it << endl;
}
//查找自定义数据类型
class Person
{
public:
    Person(string name,int age)
    {
        this->m_age = age;
        this->m_name = name;
    }
    //重载==运算符,让find知道如何对比Person类型数据
    bool operator==(const Person& p)
    {
        if (p.m_age == this->m_age && p.m_name == this->m_name)
            return true;
        else
            return false;
    }
    string m_name;
    int m_age;
};
void test02()
{
    //准备数据
    Person p1("A", 1);
    Person p2("B", 2);
    Person p3("C", 3);
    Person p4("D", 4);
    Person p5("E", 5);
    //放入容器中
    vector<Person>p;
    p.push_back(p1);
    p.push_back(p2);
    p.push_back(p3);
    p.push_back(p4);
    p.push_back(p5);
    //查找
    Person p6("A", 1);
    vector<Person>::iterator it = find(p.begin(), p.end(), p6);
    //输出,验证结果
    if (it == p.end())
        cout << "没找到" << endl;
    else
        cout << "找到了" << it->m_name << it->m_age << endl;
}
int main()
{
    test01();
    test02();
    return 0;
}

二分查找

std::binary_search 在一个已排序的范围内查找特定元素,如果找到则返回 true。

bool binary_search(iterator beg, iterator end, value);
查找指定的元素,查到返回true,否则返回false
注意:在无序列表中不可用,如果是无序序列,结果未知
beg		//开始迭代器
end		//结束迭代器
value	//查找的元素
#include<iostream>
#include<vector>
#include<algorithm>

std::vector<int> my_vector = {1, 2, 3, 4, 5};  
std::sort(my_vector.begin(), my_vector.end());  
if (std::binary_search(my_vector.begin(), my_vector.end(), 3)) {  
    std::cout << "Element 3 found" << std::endl;  
} else {  
    std::cout << "Element 3 not found" << std::endl;  
}

排序和通用算法

简介 算法名称 功能
排序 sort 升序重新排列指定范围内的元素
排序 stable_sort 与sort类似,不过保留相等元素之间的顺序关系。
反正 reverse 将指定范围内元素重新反序排序。
随机 random_shuffle 对指定范围内的元素随机调整次序。
合并 merge 合并两个有序序列,存放到另一个序列

排序

std::sort 对一个范围内的元素进行排序。

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

std::vector<int> my_vector = {5, 2, 4, 1, 3};  
std::sort(my_vector.begin(), my_vector.end());  
for (auto x : my_vector) {  
    std::cout << x << " ";  
}  
std::cout << std::endl;
//1 2 3 4 5
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void test01()
{
    vector<int>v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    //默认升序
    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(), greater<int>());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
}
int main()
{
    test01();
    return 0;
}

随机

random_shuffle(iterator beg, iterator end)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void test01()
{
    vector<int>v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    random_shuffle(v.begin(), v.end());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " " ;
    }
    cout << endl;
}
int main()
{
    test01();
    return 0;
}

合并

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

int main() {
    std::vector<int> v1 = {5, 2, 4, 1, 3};  
    std::vector<int> v2 = {5, 2, 4, 1, 3};  
    std::vector<int> v3;
    v3.resize(v1.size() + v2.size());
    std::sort(v1.begin(), v1.end());  
    for (auto x : v1) {  
        std::cout << x << " ";  
    }  
    std::cout << std::endl;
    //1 2 3 4 5

    std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
    for (auto x : v3) {
        std::cout << x << " ";  
    }  
    std::cout << std::endl;
    //1 2 3 4 5 5 2 4 1 3
  
    return 0;
} 

反转

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int val)
{
    cout << val << " ";
}
void test01()
{
    vector<int>v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    for_each(v1.begin(), v1.end(), Print);
    cout << endl;
    //反转
    reverse(v1.begin(), v1.end());
    for_each(v1.begin(), v1.end(), Print);
}
int main()
{
    test01();
    return 0;
}

复制替换删除算法

序号 算法名称 功能
拷贝 copy 将容器内指定范围内的元素拷贝到目标容器。
替换 replace 将容器指定范围的旧元素替换为新元素
替换 replace_if 将容器区间内满足条件的元素,替换成新元素
唯一 unique 清除序列中相邻的重复元素
互换 swap 互换两个容器的元素
删除 remove 删除指定范围内所有等于指定元素的元素

复制替换

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

using namespace std;

struct  Judge_Elem
{
   bool   operator()(int x)     // 判断这个值是否为3
   {
   	return  x == 6 | x== 9;
   }
};

void  Print(int  x)
{
   cout << x << " ";            // 打印元素
}


int main()
{
   	//数据都在容器中
   	vector<int> v = { 1,2,3,4,5,6 };
    vector<int> v_copy(v.size());
    
    copy(v.begin(), v.end(), v_copy.begin());

   	// 替换元素
   	replace(v.begin(), v.end(),3,9);
   	for_each(v.begin(), v.end(), Print);
   	cout << endl;

 
   	// 条件替换元素
   	replace_if(v.begin(), v.end(), Judge_Elem(), 0);
   	for_each(v.begin(), v.end(), Print);
   	cout << endl;

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

删除唯一

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

using namespace std;

void  Print(int  x)
{
   cout << x << " ";            // 打印元素
}
int main()
{
   	//数据都在容器中
   	vector<int> v1 = { 1,3,2,3,4,5,6}; 
   	//删除所有的特定元素,但是不会改变容器的大小,只会将后面的元素往前移动,
   	//并返回删除后最后一个元素的结束位置
   	vector<int>::iterator  itNewEnd=remove(v1.begin(), v1.end(), 3); 

   	//打印
   	for_each(v1.begin(), itNewEnd, Print);
   	cout << endl;   

   	//数据都在容器中
   	vector<int> v2 = { 1,2,3,3,3,4,5,6 };

   	//删除【连续相同元素】,只保留一个,但是不会改变容器的大小,只会将后面的元素往前移动,
   	//并返回删除后最后一个元素的结束位置,类似remove
   	vector<int>::iterator  itNewEnd =	unique(v2.begin(), v2.end());

   	//打印
   	for_each(v2.begin(), itNewEnd, Print);
   	cout << endl;
   
}
// 1 2 4 5 6 
// 1 2 3 4 5 6

互换

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Print
{
public:
    void operator()(int val)
    {
        cout << val << " ";
    }
};
class GreaterFive
{
public:
    bool operator()(const int& val)
    {
        return val > 5;
    }
};
void test01()
{
    vector<int>v1;
    vector<int>v2;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
        v2.push_back(i + 2);
    }
    //交换前
    for_each(v1.begin(), v1.end(), Print());
    for_each(v2.begin(), v2.end(), Print());
    cout << endl;
    //交换后
    swap(v1, v2);
    for_each(v1.begin(), v1.end(), Print());
    for_each(v2.begin(), v2.end(), Print());
}
int main()
{
    test01();
    return 0;
}

生成和异变算法

简述 算法名称 功能
填充 fill 将输入值赋给标志范围内的所有元素
转换 transform 将输入的操作作用与指定范围内的每个元素,并产生一个新的序列
生成 generate 连续调用输入的函数来填充指定的范围
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void  Print(int  x)
{
   cout << x << " ";            // 打印元素
}

class even_by_two
{
private:
	static int _x;      //  注意静态变量   
public:
	int operator()()const
	{
		return _x += 2;
	}
};
int even_by_two::_x = 0; //  初始化静态变量

void test01()
{
    vector<int> v1={1,2,3,4,5,6,7,8,9};
    vector<int> iv(10);

    for_each(v1.begin(), v1.end(), Print);
    cout << endl;
    
    fill(v1.begin(), v1.end(), 9);

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

    generate(iv.begin(), iv.end(), even_by_two());
    for_each(iv.begin(), iv.end(), Print);
    cout << endl;
    
}   
int main()
{
    test01();
    return 0;
}

数值算法

简述 算法名称 功能
累加 accumulate 计算容器元素累计总和
partial_sum 每个元素值代表指定范围内该位置前所有元素之和
内积 inner_product 内积,对应元素相乘,再求和
adjacent_difference 计算相邻元素的差
#include <iostream>
#include <vector>
#include <numeric> // 数值算法
#include <iterator> // 定义了ostream_iterator
#include<algorithm>
using namespace std;

void Print(int x){
    cout << x << " ";
};

int main(int argc, char* argv[])
{
	int arr[] = { 1, 2, 3, 4, 5 };
	vector<int> vec(arr, arr + 5);
	vector<int> vec2(arr, arr + 5);
    for_each(vec.begin(), vec.end(), Print);
    cout << endl;
    

	//  accumulate: iterator对标识的序列段元素之和,加到一个由val指定的初始值上。
	int temp;
	int val = 0;
	temp = accumulate(vec.begin(), vec.end(), val);
	cout << "accumulate(val = 0): " << temp << endl;
	val = 1;
	temp = accumulate(vec.begin(), vec.end(), val);
	cout << "accumulate(val = 1): " << temp << endl;

	// inner_product: 对两个序列做内积(对应元素相乘,再求和)并将内积加到一个输入的初始值上。
	// 这里是:1*1 + 2*2 + 3*3 + 4*4 + 5*5
	val = 0;
	temp = inner_product(vec.begin(), vec.end(), vec2.begin(), val);
	cout << "inner_product(val = 0): " << temp << endl;

	// partial_sum: 创建一个新序列,其中每个元素值代表指定范围内该位置前所有元素之和。
	// 第一次,1   第二次,1+2  第三次,1+2+3  第四次,1+2+3+4
	ostream_iterator<int> oit(cout, " "); // 迭代器绑定到cout上作为输出使用
	cout << "ostream_iterator: ";
	partial_sum(vec.begin(), vec.end(), oit);// 依次输出前n个数的和
	cout << endl;
	// 第一次,1   第二次,1-2  第三次,1-2-3  第四次,1-2-3-4
	cout << "ostream_iterator(minus): ";
	partial_sum(vec.begin(), vec.end(), oit, minus<int>());// 依次输出第一个数减去(除第一个数外到当前数的和)
	cout << endl;

	// adjacent_difference: 创建一个新序列,新序列中每个新值代表当前元素与上一个元素的差。
	// 第一次,1-0   第二次,2-1  第三次,3-2  第四次,4-3
	cout << "adjacent_difference: ";
	adjacent_difference(vec.begin(), vec.end(), oit);              // 输出相邻元素差值 后面-前面
	cout << endl;
	// 第一次,1+0   第二次,2+1  第三次,3+2  第四次,4+3
	cout << "adjacent_difference(plus): ";
	adjacent_difference(vec.begin(), vec.end(), oit, plus<int>()); // 输出相邻元素差值 后面-前面 
	cout << endl;

	return 0;
}

/*
accumulate(val = 0): 15
accumulate(val = 1): 16
inner_product(val = 0): 55
ostream_iterator: 1 3 6 10 15
ostream_iterator(minus): 1 -1 -4 -8 -13
adjacent_difference: 1 1 1 1 1
adjacent_difference(plus): 1 3 5 7 9
*/

关系集合算法

简述 算法名称 功能
交集 set_intersection 求两个容器的交集
并集 set_union 求两个容器的并集
差集 set_difference 求两个容器的差集

交并集

set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//求两个容器的交集

beg1	//容器1开始迭代器
end1	//容器1结束迭代器
beg2	//容器2开始迭代器
end2	//容器2结束迭代器
dest	//目标容器开始迭代器

# 返回值为迭代器,指向交集最后一个元素的下一个位置
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void myPrint(int val)
{
    cout << val << " ";
}
void test01()
{
    vector<int>v1={1,2,3,4,5,6,7,8,9};
    vector<int>v2={5,6,7,8,9,10,11,12,13,14};

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

    //目标容器需要提前开辟空间,最特殊的情况,大容器包含小容器
    vector<int>v3;
    v3.resize(min(v1.size(), v2.size()));
    //取交集
    vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
    for_each(v3.begin(), itEnd, myPrint);
    cout << endl;
    //如果不用返回的itEnd,会把0也给打印出来
    for_each(v3.begin(), v3.end(), myPrint);
}
int main()
{
    test01();
    return 0;
}

set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//求两个容器的并集

beg1	//容器1开始迭代器
end1	//容器1结束迭代器
beg2	//容器2开始迭代器
end2	//容器2结束迭代器
dest	//目标容器开始迭代器

# 返回值为迭代器,指向并集最后一个元素的下一个位置
vector<int>v4;
v4.resize(v1.size() + v2.size());
vector<int>::iterator ituEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v4.begin());
for_each(v4.begin(), ituEnd, myPrint);

实践操作

Vector中去重

对于STL去重,可以使用中提供的unique()函数。

unique()函数用于去除相邻元素中的重复元素(所以去重前需要对vector进行排序),只留下一个。返回去重后的尾地址。

unique()并不会删除vector中的元素,只是将重复元素替换为之后的元素,vector的大小并不会改变。

所以之后还需要调用erase()函数,删除之后的元素。

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

using namespace std;

int main(int argc, char *argv[])
{
    vector<int> nums;
    for (int i = 0; i < 10; i++)
        nums.push_back(i % 8);

    cout << "before sort..." << endl;
    for (size_t i = 0; i < nums.size(); i++)
        cout << nums[i] << "  ";
    cout << endl;

    cout << "after sort..." << endl;
    sort(nums.begin(), nums.end());
    for (size_t i = 0; i < nums.size(); i++)
        cout << nums[i] << "  ";
    cout << endl;

    auto iter = unique(nums.begin(), nums.end());
    cout << "before unique() size:" << nums.size() << "\nafter unique() size:" << nums.size() << endl;
    nums.erase(iter, nums.end());
    for (size_t i = 0; i < nums.size(); i++)
        cout << nums[i] << "  ";
    cout << endl;

    getchar();
    return 0;
}

参考资料

https://juejin.cn/post/7301496834232614951?from=search-suggest#heading-24

https://blog.csdn.net/u014779536/article/details/116380670 详细

https://www.cnblogs.com/linuxAndMcu/p/10264339.html

https://www.cnblogs.com/BeyondAnyTime/archive/2012/05/27/2520532.html

posted @ 2024-01-22 20:00  贝壳里的星海  阅读(9)  评论(0编辑  收藏  举报