C++ によるプログラミングの向上 5: STL 共通アルゴリズム

概要:

  • アルゴリズムは主に<algorithm> <functional> <numeric>ヘッダー ファイルで構成されます。
  • <algorithm>これは、すべての STL ヘッダー ファイルの中で最大であり、比較、交換、検索、走査操作、コピー、変更などをカバーします。
  • <numeric>サイズが小さく、シーケンスに対して単純な数学演算を実行するテンプレート関数がいくつか含まれているだけです。
  • <functional>一部のテンプレート クラスは、関数オブジェクトを宣言するために定義されています。

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

学習目標:

  • 一般的に使用されるトラバーサル アルゴリズムをマスターする

アルゴリズムの紹介:

  • for_each //コンテナを走査する
  • transform //コンテナを別のコンテナに移動します

1.1、for_each

機能の説明:

  • コンテナのトラバーサルを実装する

関数プロトタイプ:

  • for_each(イテレータ開始、イテレータ終了、_func);

// 走査アルゴリズムはコンテナ要素を走査します

// beg はイテレータを開始します

// end イテレータを終了します

// _func 関数または関数オブジェクト

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

//常用遍历算法for_each

//普通函数
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();
	system("pause");
	return 0;
}

概要: for_each は実際の開発で最も一般的に使用されるトラバーサル アルゴリズムであり、熟練が必要です。

for_each関数の最初の2つのパラメータはイテレータの範囲を指定する必要があり、後者のパラメータは関数またはファンクタであり、関数の内容に応じて関数が実装されます(通常の関数の場合は、関数名を渡します。ファンクターの場合は、匿名関数オブジェクトを渡す必要があります)

1.2、変換

機能の説明:

  • コンテナを別のコンテナに移動する

関数プロトタイプ:

  • transform(iterator beg1, iterator end1, iterator beg2, _func);

//beg1 ソースコンテナがイテレータを開始します

//end1 ソースコンテナの終了イテレータ

//beg2 ターゲット コンテナがイテレータを開始します

//_func 関数または関数オブジェクト

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

//常用遍历算法  搬运 transform

class TransForm
{
public:
	int operator()(int val)
	{
		return val;
	}
};

class MyPrint
{
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(), MyPrint());
}

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

要約:

変換関数の 1 番目と 2 番目のパラメータはそれぞれソース コンテナの開始イテレータと終了イテレータ、3 番目のパラメータはターゲット コンテナの開始イテレータ、4 番目のパラメータは挿入方法を決定する関数またはファンクタです。

(注: ターゲットコンテナは移動する前に事前にスペースを空ける必要があります)

2. 一般的に使用される検索アルゴリズム

学習目標:

  • 一般的な検索アルゴリズムをマスターする

アルゴリズムの紹介:

  • find //要素を検索
  • find_if //条件に基づいて要素を検索
  • 隣接_find //隣接する繰り返し要素を検索します
  • binary_search //二分探索法
  • count //要素数をカウントする
  • count_if //条件に従って要素数をカウントする

2.1、探す

機能の説明:

  • 指定された要素を検索し、指定された要素を返すイテレータを検索し、終了イテレータを返すイテレータを検索します。 end()

関数プロトタイプ:

  • find(iterator beg, iterator end, value);

// 要素を値で検索し、見つかった場合は指定された位置のイテレータを返し、見つからない場合は終了イテレータの位置を返します。

// beg はイテレータを開始します

// end イテレータを終了します

// 検索する値要素

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

//常用查找算法
//find

//查找内置数据类型
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:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	//重载==
	bool operator==(const Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		return false;
	}

public:
	string m_Name;
	int m_Age;
};

//查找 自定义数据类型
void test02() {

	vector<Person> v;

	//创建数据
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);

	//插入数据
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	vector<Person>::iterator it = find(v.begin(), v.end(), p2);
	if (it == v.end())
	{
		cout << "没有找到!" << endl;
	}
	else
	{
		cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;
	}
}

int main()
{
	//test01();
	test02();
	return 0;
}

概要: find を使用して、コンテナ内の指定された要素を検索します。戻り値は反復子であるため、結果を指すには反復子ポインターが必要です。

(注: データがカスタム タイプの場合、カスタム データ タイプは比較できないため、== 記号をオーバーロードする必要があります)

2.2、find_if

機能の説明:

  • 条件による要素の検索

関数プロトタイプ:

  • find_if(iterator beg, iterator end, _Pred);

// 要素を値で検索し、見つかった場合は指定された位置のイテレータを返し、見つからない場合は終了イテレータの位置を返します。

// beg はイテレータを開始します

// end イテレータを終了します

// _Pred 関数または述語 (bool 型ファンクターを返す)

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

//常用查找算法  find_if

//内置数据类型
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 + 1);
	}

	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)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
public:
	string m_Name;
	int m_Age;
};

class Greater20
{
public:
	bool operator()(Person& p)
	{
		return p.m_Age > 20;
	}
};

void test02() {

	vector<Person> v;

	//创建数据
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	vector<Person>::iterator it = find_if(v.begin(), v.end(), Greater20());

	if (it == v.end())
	{
		cout << "没有找到!" << endl;
	}
	else
	{
		cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;
	}
}

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

概要: find_if は find に似ていますが、find は値を直接検索するのに対し、find_if は関数またはファンクターを通じて検索条件を決定します。

2.3、隣接検索

機能の説明:

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

関数プロトタイプ:

  • 隣接_find(イテレータの開始、イテレータの終了);

// 隣接する重複要素を検索し、隣接する要素の最初の位置のイテレータを返します。

// beg はイテレータを開始します

// end イテレータを終了します

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

//常用查找算法  adjacent_find

void test01()
{
	vector<int> v;
	v.push_back(0);
	v.push_back(2);
	v.push_back(0);
	v.push_back(1);
	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;
	}
}

int main()
{
	test01();
	return 0;
}

概要:面接で、隣接する繰り返し要素の検索に関する質問がある場合は、STL の隣接する_find アルゴリズムを使用することを忘れないでください。

2.4、バイナリ検索

機能の説明:

  • 指定された要素が存在するかどうかを調べる

関数プロトタイプ:

  • bool binary_search(iterator beg, iterator end, value);

//指定された要素を検索し、見つかった場合は true を返し、それ以外の場合は false を返します。

// 注: 順序付けされていないシーケンスでは使用できません

// beg はイテレータを開始します

// end イテレータを終了します

// 検索する値要素

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

//常用查找算法 binary_search

void test01()
{
	vector<int>v;

	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	//v.push_back(2); 如果是无序序列,结果未知

	//二分查找  容器中是否有9元素
	//注意:容器必须是有序的升序序列
	bool ret = binary_search(v.begin(), v.end(), 9);
	if (ret)
	{
		cout << "找到了" << endl;
	}
	else
	{
		cout << "未找到" << endl;
	}
}

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

概要:二分検索方法は非常に効率的ですが、検索されるコンテナ内の要素は昇順に並べられている必要があります。

2.5、カウント

機能の説明:

  • 統計要素の数

関数プロトタイプ:

  • count(イテレータの開始、イテレータの終了、値);

// 要素の出現数をカウントします

// beg はイテレータを開始します

// end イテレータを終了します

// 統計の値要素

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

//常用查找算法 count

//内置数据类型
void test01()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(4);
	v.push_back(5);
	v.push_back(3);
	v.push_back(4);
	v.push_back(4);

	int num = count(v.begin(), v.end(), 4);

	cout << "4的个数为: " << num << endl;
}

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

void test02()
{
	vector<Person> v;

	Person p1("刘备", 35);
	Person p2("关羽", 35);
	Person p3("张飞", 35);
	Person p4("赵云", 30);
	Person p5("曹操", 25);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);

	Person p("诸葛亮", 35);

	int num = count(v.begin(), v.end(), p);
	cout << "num = " << num << endl;
}

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

概要:カスタム データ型をカウントするときは、operator== をオーバーロードする必要があります。

count の定義から、カスタム データを比較する場合、count の == 記号ではカスタム データを比較できないことがわかります。そのため、コード内で == 記号をオーバーロードして、2 つが等しいと判断するための条件を与える必要があります。 。

2.6、count_if

機能の説明:

  • 条件に応じて要素数をカウントする

関数プロトタイプ:

  • count_if(イテレータ開始、イテレータ終了、_Pred);

// 条件に基づいて要素の出現数をカウントします

// beg はイテレータを開始します

// end イテレータを終了します

// _Pred述語

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

//常用查找算法  count_if

class Greater4
{
public:
	bool operator()(int val)
	{
		return val >= 4;
	}
};

//内置数据类型
void test01()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(4);
	v.push_back(5);
	v.push_back(3);
	v.push_back(4);
	v.push_back(4);

	int num = count_if(v.begin(), v.end(), Greater4());

	cout << "大于等于4的个数为: " << num << endl;
}

//自定义数据类型
class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

class AgeLess35
{
public:
	bool operator()(const Person& p)
	{
		return p.m_Age < 35;
	}
};
void test02()
{
	vector<Person> v;

	Person p1("刘备", 35);
	Person p2("关羽", 35);
	Person p3("张飞", 35);
	Person p4("赵云", 30);
	Person p5("曹操", 25);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);

	int num = count_if(v.begin(), v.end(), AgeLess35());
	cout << "小于35岁的个数:" << num << endl;
}

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

概要: count_if と count の違いは、count_if は述語の条件に基づいてデータをカウントできるのに対し、count は値に基づいてのみカウントできることです。

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

学習目標:

  • よく使用される並べ替えアルゴリズムをマスターする

アルゴリズムの紹介:

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

3.1、並べ替え

機能の説明:

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

関数プロトタイプ:

  • sort(イテレータ開始、イテレータ終了、_Pred);
  • // 要素を値で検索し、見つかった場合は指定された位置のイテレータを返し、見つからない場合は終了イテレータの位置を返します。
  • // beg はイテレータを開始します // end はイテレータを終了します
  • // _Pred述語
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include <functional>

//常用排序算法  sort

void myPrint(int val)
{
	cout << val << " ";
}

class great
{
public:
	bool operator()(int val1, int val2)
	{
		return val1 > val2;
	}
};

void test01() 
{
	vector<int> v;

	v.push_back(10);
	v.push_back(30);
	v.push_back(50);
	v.push_back(20);
	v.push_back(40);

	//sort默认从小到大排序
	sort(v.begin(), v.end());
	for_each(v.begin(), v.end(), myPrint);
	cout << endl;

	//从大到小排序
	sort(v.begin(), v.end(), greater<int>());
	for_each(v.begin(), v.end(), myPrint);
	cout << endl;
}

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

概要:デフォルトでは、sort は小さいものから大きいものへの昇順でソートされますが、降順でソートしたい場合は、述語を追加してソート方法を設定する必要があります。

sort は最も一般的に使用されるアルゴリズムの 1 つであり、熟練が必要です

3.2、ランダムシャッフル

機能の説明:

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

関数プロトタイプ:

  • random_shuffle(イテレータの開始、イテレータの終了);
  • // 指定された範囲内の要素の順序をランダムに調整します
  • // beg はイテレータを開始します
  • // end イテレータを終了します
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include <ctime>

//常用排序算法  random_shuffle

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{
	//随机种子随时间改变
	srand((unsigned int)time(NULL));

	vector<int> v;

	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	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();
	system("pause");
	return 0;
}

概要: シャッフル アルゴリズム randan_shuffle の方が実用的です。使用する場合は、乱数シードを忘れずに追加してください:srand((usingned int)time(NULL));時間ヘッダー ファイルを追加することを忘れないでください。#include <ctime>

3.3、マージ

機能の説明:

  • 2 つのコンテナ要素がマージされ、別のコンテナに保存されます

関数プロトタイプ:

  • merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// コンテナ要素はマージされ、別のコンテナに保存されます

// 注: 2 つのコンテナを注文する必要があります

// beg1 コンテナ 1 がイテレータを開始します

// end1 コンテナ 1 終了イテレータ

// beg2 コンテナ 2 がイテレータを開始します

// end2 コンテナ 2 の終了イテレータ

// dest ターゲット コンテナがイテレータを開始します

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

//常用排序算法  merge

class myPrint
{
public:
	void operator()(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 + 1);
	}

	vector<int> vtarget;

	//目标容器需要提前开辟空间
	vtarget.resize(v1.size() + v2.size());

	//合并  需要两个有序序列
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vtarget.begin());
	for_each(vtarget.begin(), vtarget.end(), myPrint());
	cout << endl;
}

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

要約:

1. マージによってマージされた 2 つのコンテナーは順序どおりである必要があり、マージされたコンテナーも順序どおりである必要があります。

2. マージを行う前に、ターゲットコンテナに事前に十分なメモリ領域が割り当てられている必要があります。

3.4、リバース

機能の説明:

  • コンテナ内の要素を反転します

関数プロトタイプ:

  • reverse(イテレータの開始、イテレータの終了);
  • //指定した範囲の要素を反転します
  • // beg はイテレータを開始します
  • // end イテレータを終了します
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>

//常用排序算法  reverse

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{
	vector<int> v;
	v.push_back(10);
	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;

	cout << "反转后: " << endl;

	reverse(v.begin(), v.end());
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
}

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

概要: reverse は、面接の質問に含まれる可能性のある区間内の要素を反転します。

4. 一般的なコピーおよび置換アルゴリズム

学習目標:

  • 一般的なコピーおよび置換アルゴリズムをマスターする

アルゴリズムの紹介:

  • copy // コンテナ内の指定された範囲の要素を別のコンテナにコピーします
  • replace // コンテナ内の指定された範囲内の古い要素を新しい要素に変更します
  • replace_if //指定された範囲を満たすコンテナ内の要素を新しい要素に置き換えます
  • swap // 2 つのコンテナの要素を交換します

4.1、コピー

機能の説明:

  • コンテナ内の指定された範囲の要素を別のコンテナにコピーします

関数プロトタイプ:

  • copy(iterator beg, iterator end, iterator dest);

// 要素を値で検索し、見つかった場合は指定された位置のイテレータを返し、見つからない場合は終了イテレータの位置を返します。

// beg はイテレータを開始します

// end イテレータを終了します

// dest ターゲットの開始イテレータ

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

//常用拷贝算法  copy

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{
	vector<int> v1;

	for (int i = 0; i < 10; i++) 
	{
		v1.push_back(i + 1);
	}

	vector<int> v2;
	v2.resize(v1.size());

	//拷贝
	copy(v1.begin(), v1.end(), v2.begin());

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

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

概要: コピー アルゴリズムを使用してコピーする場合は、事前にターゲット コンテナーにスペースを空けておくことを忘れないでください。

4.2、交換

機能の説明:

  • コンテナの指定範囲内の古い要素を新しい要素に変更します。

関数プロトタイプ:

  • replace(iterator beg, iterator end, oldvalue, newvalue);

//範囲内の古い要素を新しい要素に置き換えます

// beg はイテレータを開始します

// end イテレータを終了します

// oldvalue 古い要素

// newvalue 新しい要素

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

//替换算法  replace

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{
	vector<int> v;

	v.push_back(20);
	v.push_back(30);
	v.push_back(20);
	v.push_back(40);
	v.push_back(50);
	v.push_back(10);
	v.push_back(20);

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

	//将容器中的20 替换成 2000
	cout << "替换后:" << endl;
	replace(v.begin(), v.end(), 20, 2000);
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
}

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

概要: replace は、条件を満たす間隔内の要素を置き換えます。

4.3、replace_if

機能の説明:

  • 区間内の条件を満たす要素を指定された要素に置き換えます

関数プロトタイプ:

  • replace_if(iterator beg, iterator end, _pred, newvalue);

//条件に従って要素を置換し、条件を満たす要素を指定された要素に置換します

// beg はイテレータを開始します

// end イテレータを終了します

// _pred述語

// 新しい要素を新しい値に置き換えます

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

//常用拷贝和替换算法 replace_if

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

class ReplaceGreater30
{
public:
	bool operator()(int val)
	{
		return val >= 30;
	}
};

void test01()
{
	vector<int> v;

	v.push_back(20);
	v.push_back(30);
	v.push_back(20);
	v.push_back(40);
	v.push_back(50);
	v.push_back(10);
	v.push_back(20);

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

	//将容器中大于等于的30 替换成 3000
	cout << "替换后:" << endl;
	replace_if(v.begin(), v.end(), ReplaceGreater30(), 3000);
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
}

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

概要: replace_if は条件に従って検索し、ファンクターを使用して条件を満たすように柔軟にフィルタリングできます。

4.4、スワップ

機能の説明:

  • 2 つのコンテナの要素を交換する

関数プロトタイプ:

  • swap(container c1,container c2); // 2 つのコンテナの要素を交換 // c1 コンテナ 1 // c2 コンテナ 2
#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>

//常用拷贝和替换算法  swap

class myPrint
{
public:
	void operator()(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 + 100);
	}

	cout << "交换前: " << endl;
	for_each(v1.begin(), v1.end(), myPrint());
	cout << endl;
	for_each(v2.begin(), v2.end(), myPrint());
	cout << endl;

	cout << "交换后: " << endl;
	swap(v1, v2);
	for_each(v1.begin(), v1.end(), myPrint());
	cout << endl;
	for_each(v2.begin(), v2.end(), myPrint());
	cout << endl;
}

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

概要: コンテナを交換するときは、交換するコンテナが同じ種類である必要があることに注意してください。

5. 一般的に使用される算術生成アルゴリズム

学習目標:

  • 一般的な算術生成アルゴリズムをマスターする

知らせ:

  • 算術生成アルゴリズムは小規模なアルゴリズムであり、それを使用するときにインクルードされるヘッダー ファイルは #include <numeric> です。

アルゴリズムの紹介:

  • accumulate // コンテナ要素の累積合計を計算します
  • fill // 要素をコンテナに追加します

5.1、蓄積する

機能の説明:

  • 範囲内のコンテナ要素の累積合計を計算します。

関数プロトタイプ:

  • 蓄積(イテレータ開始、イテレータ終了、値);
  • // コンテナ要素の累積合計を計算します
  • // beg はイテレータを開始します
  • // end イテレータを終了します
  • // value 開始値 (開始値と累積合計に基づく)
#include <iostream>
using namespace std;
#include <numeric>
#include <vector>

//常用算术生成算法
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 = " << total << endl;
}

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

まとめ:accumulateを使うときはヘッダファイルに注意してください#include <numeric>このアルゴリズムは非常に実用的です。

最後のパラメータは開始値であり、最終結果は開始値にコンテナの累積和を加えたものであることに注意してください。

5.2、塗りつぶし

機能の説明:

  • コンテナに指定された要素を埋め込みます

関数プロトタイプ:

  • fill(イテレータの開始、イテレータの終了、値);
  • // コンテナに要素を埋め込みます
  • // beg はイテレータを開始します
  • // end イテレータを終了します
  • // 値を埋めた値
#include <iostream>
using namespace std;
#include <numeric>
#include <vector>
#include <algorithm>

//常用算术生成算法  fill

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{

	vector<int> v;
	v.resize(10);

	//填充
	fill(v.begin(), v.end(), 100);

	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
}

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

概要: fill を使用して、コンテナ範囲内の要素を指定した値で埋めます。

6. 一般的に使用される集合アルゴリズム

学習目標:

  • 共通セットアルゴリズムをマスターする

アルゴリズムの紹介:

  • set_intersection // 2 つのコンテナの交差部分を見つけます
  • set_union // 2 つのコンテナの結合を見つけます
  • set_difference // 2 つのコンテナ間の違いを見つけます

6.1、set_intersection (交差点)

機能の説明:

  • 2 つのコンテナの交差部分を見つける

関数プロトタイプ:

  • set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 2 つのセットの共通部分を見つけます

// 注: 2 つのセットは順序付けされたシーケンスである必要があります

// beg1 コンテナ 1 がイテレータを開始します

// end1 コンテナ 1 終了イテレータ

// beg2 コンテナ 2 がイテレータを開始します

// end2 コンテナ 2 の終了イテレータ

// dest ターゲット コンテナがイテレータを開始します

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

//常用集合算法  set_intersection

class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void test01()
{
	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
	}

	/*v2.push_back(5);
	v2.push_back(8);
	v2.push_back(9);
	v2.push_back(6);
	v2.push_back(10);*/

	vector<int> vTarget;
	//取两个里面较小的值给目标容器开辟空间
	vTarget.resize(min(v1.size(), v2.size()));

	//返回目标容器的最后一个元素的迭代器地址
	vector<int>::iterator itEnd = 
		set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

	for_each(vTarget.begin(), itEnd, myPrint());
	cout << endl;
}

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

要約:

  • 交差する 2 つのセットは、昇順の順序付けされたシーケンスである必要があります。

  • ターゲット コンテナは、領域を空けるために2 つのコンテナから小さい方の値を取得する必要があります。

  • set_intersection の戻り値は、交差部分の最後の要素の位置です。

6.2、set_union

機能の説明:

  • 2 つの集合の和集合を求めます

関数プロトタイプ:

  • set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 2 つの集合の和集合を求めます

// 注: 2 つのセットは順序付けされたシーケンスである必要があります

// beg1 コンテナ 1 がイテレータを開始します

// end1 コンテナ 1 終了イテレータ

// beg2 コンテナ 2 がイテレータを開始します

// end2 コンテナ 2 の終了イテレータ

// dest ターゲット コンテナがイテレータを開始します

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

//常用集合算法  set_union

class myPrint
{
public:
	void operator()(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 itEnd =
		set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

	for_each(vTarget.begin(), itEnd, myPrint());
	cout << endl;
}

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

要約:

  • 2 つのセットの和集合に必要な順序付き昇順シーケンスを見つけます。
  • ターゲット コンテナでは、スペースを空けるために2 つのコンテナを追加する必要があります。

  • set_union の戻り値は、共用体の最後の要素の位置です。

6.3、異なるセット

機能の説明:

  • 2 つのセットの差を見つけます

関数プロトタイプ:

  • set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

// 2 つのセットの差を見つけます

// 注: 2 つのセットは順序付けされたシーケンスである必要があります

// beg1 コンテナ 1 がイテレータを開始します

// end1 コンテナ 1 終了イテレータ

// beg2 コンテナ 2 がイテレータを開始します

// end2 コンテナ 2 の終了イテレータ

// dest ターゲット コンテナがイテレータを開始します

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

//常用集合算法  set_different

class myPrint
{
public:
	void operator()(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();
	system("pause");
	return 0;
}

要約:

  • 2 つの差分セットの必要な順序付き昇順シーケンスを見つけます。
  • ターゲット コンテナは、領域を空けるために2 つのコンテナから大きい方の値を取得する必要があります。

  • set_difference の戻り値は、差分セット内の最後の要素の位置です。
  • セットの差セットの順序は結果に影響します

おすすめ

転載: blog.csdn.net/qq_63388834/article/details/134969434