C++ STL 学習メモ (3)

トリビア

これは STL 学習ノートの 3 番目のパートです。最初の 2 つはそれぞれコンテナーと関数オブジェクトについてです。パート 1
: STL 学習ノート (1)—コンテナー
パート 2: STL 学習ノート (2)

概要

 アルゴリズムは主にヘッダー ファイル<algorithm>、から構成されます<numeric><functional>

  <algorithm>これはすべての STL ヘッダー ファイルの中で最大であり、一般的に使用される機能には、比較、交換、検索、走査、コピー、変更、反転、ソート、マージなどが含まれます
  <numeric>。シーケンスに対する加算や乗算などの単純な演算のための関数。
  <functional>一部のテンプレート クラスは関数オブジェクトを宣言するために定義されています。

1. 一般的に使用されるトラバーサル アルゴリズム

for_each//コンテナを走査
transform//コンテナを別のコンテナに移動

1.1 for_each

/* 
遍历算法 遍历容器元素 
@param beg 开始迭代器 
@param end 结束迭代器 
@param _callback 函数回调或者函数对象 
@return 函数对象 
*/
for_each(iterator beg, iterator end, _callback);

概要:for_each通常のパラメータとファンクタの両方を使用できますが、通常の関数を使用するには関数名のみが必要です。ファンクタを使用する場合はファンクタの匿名オブジェクトが必要です。

void myPrint1(int val){
    
    
	cout<<val<<" ";
}
class myPrint2{
    
    
	public:
		void operator()(int val){
    
    
			cout<<val<<" ";
		}
};
for_each(v.begin(),v.end(),myPrint1); 
for_each(v.begin(),v.end(),myPrint2()); 

1.2 変換

関数の説明:
  指定されたコンテナ範囲の要素を別のコンテナに移動します
。 関数プロトタイプ:

/*
transform算法 将指定容器区间元素搬运到另一容器中 
注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存 
@param beg1 源容器开始迭代器 
@param end1 源容器结束迭代器 
@param beg2 目标容器开始迭代器 
@param _cakkback 回调函数或者函数对象 
@return 返回目标容器迭代器 
*/
transform(iterator beg1, iterator end1, iterator beg2, _func);

例:

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


class myPrint{
    
    //函数用来遍历 
	public:
		void operator()(int val){
    
    
			cout<<val<<" ";
		}
};

class myTransform{
    
    //函数用来 搬运容器的同时对值进行操作 
	public:
		int operator()(int val){
    
    
			return val+100;
		}
};

void test01(){
    
    
	vector<int>v;
	for(int i=0;i<10;i++){
    
    
		v.push_back(i);
	} 
	
	vector<int>v2;
	v2.resize(v.size());
	
	transform(v.begin(),v.end(),v2.begin(),myTransform());
	for_each(v2.begin(),v2.end(),myPrint());
}

int main(){
    
    
	test01();
	system("pause");
	return 0;
}

2. 一般的な検索アルゴリズム

find//要素の検索
find_if//条件による要素の検索
adjacent_find//隣接する繰り返し要素の検索
binary_search//二分探索法
count//統計要素数
count_if//統計条件による要素数

2.1 見つける

機能の説明:

指定された要素を検索し、指定された要素を返すイテレータを検索します。見つからない場合は、終了イテレータを返します。 end()

関数プロトタイプ:

find(iterator beg, iterator end, value);
// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
// beg 开始迭代器
// end 结束迭代器
// value 查找的元素

注: ユーザー定義のデータ型は、検索時に == 演算子をオーバーロードする必要があります。演算子は、見つかったかどうかに関係なく反復子を返します。

内置数据类型
vector<int>::iterator it = find(v.begin(),v.end(),5);
if(it != v.end()){
    
    
    cout<< *it <<endl;
}else
    cout<<"not found"<<endl;


自定义数据类型
class Person{
    
    
public:
    Person(string name,int age):_name(name),_age(age){
    
    }
    //重载==
	bool operator==(const Person&p) {
    
    
		if(this->_name == p._name && this->_age == p._age){
    
    
            return true;
        }
        else{
    
    
            return false;
        }
	}
    string _name;
    int _age;
};

void test02(){
    
    
    vector<Person>v;
    v.push_back(Person("zhangsan",20));
    v.push_back(Person("lisi",30));
    v.push_back(Person("wangwu",40));
    
    vector<Person>::iterator it = find(v.begin(),v.end(),Person("lisi",30));
    
    if(it != v.end()){
    
    
        cout<< it-> _name <<endl;
    }else
        cout<<"not found"<<endl;
}

2.2 find_if

機能の説明:

条件による要素の検索

関数プロトタイプ:

find_if(iterator beg, iterator end, _Pred);
// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
// beg 开始迭代器// end 结束迭代器
// _Pred 函数或者谓词(返回bool类型的仿函数)

知らせ:

内置数据类型
class greaterFive{
    
    
    public:
    bool operator()(int a){
    
    
        return a>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:
	Person(string name, int age):_name(name),_age(age){
    
    }
    string _name;
    int _age; 
};

class greater9{
    
    
	public:
		bool operator()(Person& p){
    
    
			return p._age>9;
		}
};

void test02(){
    
    
	vector<Person>v;
	v.push_back(Person("aaa", 10));
	v.push_back(Person("bbb", 20));
	v.push_back(Person("ccc", 30));
	v.push_back(Person("ddd", 40));
	
	vector<Person>::iterator it = find_if(v.begin(),v.end(),greater9());
	cout<<it->_age<<endl;
}

2.3 隣接検索

機能の説明:

隣接する重複要素を検索する

関数プロトタイプ:

adjacent_find(iterator beg, iterator end);
// 查找相邻重复元素,返回相邻元素的第一个位置的迭代器
// beg 开始迭代器
// end 结束迭代器

2.4 バイナリ検索

機能の説明:

指定された要素が存在するかどうかを確認します。注: 順序付けられていないシーケンスでは使用できません。

関数プロトタイプ:

bool binary_search(iterator beg, iterator end, value);
// 查找指定的元素,查到 返回true 否则false
// 注意: 在无序序列中不可用
// beg 开始迭代器
// end 结束迭代器
// value 查找的元素

注:いわゆる順序付きシーケンスとは、大きいものから小さいもの、または小さいものから大きいものに配置されたシーケンスを指します。1 から 10 まで増加するコンテナーの最後に 2 を挿入すると、このコンテナーにはアルゴリズムを適用できません。

2.5カウント

機能の説明:

統計要素の数

関数プロトタイプ:

count(iterator beg, iterator end, value);
// 统计元素出现次数
// beg 开始迭代器
// end 结束迭代器
// value 统计的元素
统计内置数据类型
int num=count(v.begin(),v.end(),10);
cout<<num<<endl;

统计自定义数据类型
class Person{
    
    
public:
    Person(int id,string name):_id(id),_name(name){
    
    }
    bool operator==(const Person& p){
    
    
    	if(p._id==this->_id)
    		return true;
    	else
    		return false;
    }
    int _id;
    string _name;
};
//怎么用
int num=count(v.begin(), v.end(), Person(3,"adsf")) ;

2.6 count_if

機能の説明:

条件ごとに要素の出現をカウントする

関数プロトタイプ:

count_if(iterator beg, iterator end,_Pred);
// 按条件统计元素出现次数
// beg 开始迭代器
// end 结束迭代器
// _Pred 谓词

このセクションの例は基本的に find_if セクションの例と同じであるため、記述しません。





3. 一般的に使用される並べ替えアルゴリズム

アルゴリズムの概要:

sort//コンテナ内の要素を並べ替えます
random_shuffle//指定範囲内の要素をシャッフルして順序をランダムに調整します
merge//コンテナ要素はマージされ、別のコンテナに格納されます
reverse//指定範囲内の要素を反転します

3.1 ソート

機能の説明:

コンテナ内の要素を並べ替える

関数プロトタイプ

sort(iterator beg, iterator end, _Pred);
//按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
//beg 开始迭代器
//end 结束迭代器
/*_Pred 谓词,不写默认升序排列;
	需要一个返回值是bool类型的()重载
	也可以是STL内部的函数对象
*/
sort(v1.begin(),v1.end());
for(auto i:v1) cout<<i<<" ";
cout<<endl;

sort(v1.begin(), v1.end(),greater<int>());
for(auto i:v1) cout<<i<<" ";
cout<<endl;

3.2 ランダムシャッフル

ランダムシャッフル関数の説明:

指定した範囲の要素をシャッフルして順序をランダムに調整します

関数プロトタイプ:

random shuffle(iterator beg, iterator end);
//指定范围内的元素随机调整次序
//beg 开始迭代器
//end 结束迭代器

srand((unsigned int)time(NULL));このスクランブル アルゴリズムはランダム関数シードに依存しているため、各スクランブルの結果が異なることを保証するために、 使用時にランダム シードを追加する必要があります。time.hヘッダー ファイルを忘れずにインクルードしてください

/*示例*/
#include<time.h>
void test02(){
    
    
    srand((unsigned int)time(NULL));//随机数种子

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

    random_shuffle(v1.begin(), v1.end());
    for(auto i : v1)
        cout << i << " ";
}

3.3 マージ

マージ関数の説明:

两个容器元素合并,并存储到另一容器中

函数原型:

merge(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
//容器元素合并,并存储到另一容器中
//注意:两个容器必须是有序的
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器开始迭代器

警告:

 ①两个容器应均为有序序列,且排序方式相同
 ②在用目标容器之前需要提前给目标容器分配空间
vTarget.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

3.4 reverse

reverse 功能描述:

将容器内元素进行反转, 反转指定范围的元素

函数原型:

reverse(iterator beg, iterator end);
//反转指定范围的元素
//beg开始迭代器
//end结束迭代器

4.常用拷贝和替换算法

算法简介:

copy//容器内指定范围的元素拷贝到另一容器中
replace//将容器内指定范围的旧元素修改为新元素
replace_if //容器内指定范围满足条件的元素替换为新元素
swap //互换两个容器的元素

4.1 copy

copy 功能描述:

容器内指定范围的元素拷贝到另一容器中

函数原型:

copy(iterator beg,iterator end,iterator dest);
//beg开始迭代器
//end结束迭代器
//dest目标起始迭代器

注意:

dest应该提前 reszie 分配空间
意义不大,可以直接用=赋值;

4.2 replace

replace 功能描述

将区间内旧元素 替换成 新元素

函数原型:

replace(iterator beg,iterator end,oldvalue,newvalue)
//将区间内旧元素  替换成 新元素
//beg开始迭代器
//end结束迭代器
//oldvalue 旧元素
//newvalue 新元素
#include<iostream>
using namespace std;
#include<vector>   
#include<algorithm>

class MyPrint{
    
    
public:
	void operator()(int val){
    
    
		cout << val << " ";
	}
};
//常用拷贝和替换算法  replace
void test01(){
    
    
	vector<int>v;
	v.push_back(20);
	v.push_back(30);
	v.push_back(50);
	v.push_back(20);
	v.push_back(40);

	cout << "替换前:" << endl;
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;

	//将20替换为2000
	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;
}

4.3 replace_if

replace 功能描述

将区间内满足条件的旧元素 替换成 新元素,需要重载()符号

函数原型:

replace_if(iterator beg,iterator end,_pred,newvalue)
//将区间内旧元素  替换成 新元素
//beg开始迭代器
//end结束迭代器
//_pred 谓词   重载()符号
//newvalue 新元素

4.4 swap

swap 功能描述

 互换两个容器的元素,应是两个相同类型的容器

函数原型:

swap(container c1,container c2);
//将区间内旧元素  替换成 新元素
//互换两个容器的元素
//c1容器1
//c2容器2

5.常用算术生成算法

注意:

 算术生成算法属于小型算法,使用时包含头文件为#include< numeric>

算法简介:

accumulate//计算区间内 容器元素累计总和
fill //向容器中添加元素

5.1 accumulate

accumulate 功能描述

计算容器元素累计总和

函数原型:

accumulate<iterator beg,iterator end,value>
//beg开始迭代器
//end结束迭代器
//value 起始值

例子:
int total = accumulate(v.begin(),v.end(),0);

5.2 fill

fill 功能描述

向容器中填充元素

函数原型:

fill(iterator beg,iterator end,value)
//向容器中填充元素
//beg开始迭代器
//end结束迭代器
//value 填充的值

例子:
fill(v.begin(), v.end(), 100);
注意:

 如果容器没有分配空间应该先分配空间再调用此函数

6.常用集合算法

算法简介:
set_intersection //求两个容器的交集
set_union//求两个容器的并集
set_difference //求两个容器的差集

6.1 set_intersection

set_intersection 功能描述

 求两个集合的交集,两个集合必须是有序序列

函数原型:

set_intersection(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
//求两个容器的交集
//beg1容器1开始迭代器
//end1容器1结束迭代器
//beg2容器2开始迭代器
//end2容器2结束迭代器
//dest  目标容器开始迭代器

例子:
vTarget.resize(min(v1.size(), v2.size()));
vector::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

注意:

 目标容器应该提前开辟空间(取小容器的size)
 两个集合必须是有序序列
 会返回交集中最后一个元素的位置

6.2 set_union

set_union 功能描述

 求两个集合的并集

函数原型:

set_union(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
//求两个容器的并集
//beg1容器1开始迭代器
//end1容器1结束迭代器
//beg2容器2开始迭代器
//end2容器2结束迭代器
//dest  目标容器开始迭代器

例子:
vTarget.resize(v1.size() + v2.size());
vector::iterator itEnd = vector::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

注意:

两个集合必须是有序序列
特殊情况 两个大容器没有交集,并集就是两个容器size相加
 会返回交集中最后一个元素的位置

6.3 set_difference

功能描述:

求两个集合的差集

函数原型:

set_difference(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
//求两个集合的差集  
//注意:两个集合必须是有序序列
//beg1容器1开始迭代器
//end1容器1结束迭代器
//beg2容器2开始迭代器

//end2容器2结束迭代器

//dest  目标容器开始迭代器

例子:
vTarget.resize(max(v1.size() , v2.size()));
vector::iterator itEnd = vector::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

注意:

两个集合必须是有序序列
特殊情况 两个大容器没有交集,并集就是取大的size
 会返回交集中最后一个元素的位置

おすすめ

転載: blog.csdn.net/Stanford_sun/article/details/122793330