Algorithm 算法
STL 算法部分主要由头文件,,组成。
要使用 STL 中的算法函数必须包含头文件,
对于数值算法须包含,
中则定义了一些模板类,用来声明函数对象。
排序
| 函数名 | 函数功能 | 函数声明 |
|-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| sort | 以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。 | template<class RanIt> void sort(RanIt first, RanIt last); |
| | | template<class RanIt, class Pred> void sort(RanIt first, RanIt last, Pred pr); |
| stable_sort | 与 sort 类似,不过保留相等元素之间的顺序关系。 | template<class BidIt> void stable_sort(BidIt first, BidIt last); |
| | | template<class BidIt, class Pred> void stable_sort(BidIt first, BidIt last, Pred pr); |
| partition | 对指定范围内元素重新排序,使用输入的函数,把结果为 true 的元素放在结果为 false 的元素之前。 | template<class BidIt, class Pred> BidIt partition(BidIt first, BidIt last, Pred pr); |
| stable_partition| 与 partition 类似,不过不保证保留容器中的相对顺序。 | template<class FwdIt, class Pred> FwdIt stable_partition(FwdIt first, FwdIt last, Pred pr); |
| random_shuffle | 对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作。 | template<class RanIt> void random_shuffle(RanIt first, RanIt last); |
| | | template<class RanIt, class Fun> void random_shuffle(RanIt first, RanIt last, Fun& f); |
sort()
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(int &v)
{
cout<<v<<" ";
}
int main()
{
vector<int> vi;
for(int i=0; i<5; i++) vi.push_back(i);
sort(vi.begin(),vi.end(),greater<int>());
sort(vi.begin(),vi.end(),less_equal<int>());
stable_sort(vi.begin(),vi.end(),greater_equal<int>());
for_each(vi.begin(),vi.end(),print);
return 0;
}
partition()
#include <iostream>
#include <vector>
#include <algorithm> // 包含partition和stable_partition的头文件
using namespace std;
// 判断一个整数是否为奇数的函数
bool isodd(int i)
{
return (i % 2) == 1; // 如果i是奇数,返回true;否则返回false
}
int main()
{
// 定义一个包含10个整数的数组
int data[10] = {3, 6, 9, 2, 5, 8, 1, 4, 7, 0};
// 使用数组data初始化一个vector
vector<int> vi(data, data + 10);
// 使用partition函数将vector中的元素按isodd函数的返回值进行分区
// 奇数会被移动到vector的前面,偶数会被移动到vector的后面
auto it = partition(vi.begin(), vi.end(), isodd);
// stable_partition(vi.begin(), vi.end(), isodd);
sort(vi.begin(),it,less<int>()); // 排序前半部分
sort(it, vi.end(), less<int>()); // 排序后半部分
// 遍历并输出vector中的所有元素
for (auto i : vi)
{
cout << i << endl;
}
return 0;
}
random_shuffle()
random_shuffle 在C++11及以后的版本中已经被弃用,取而代之的是 std::shuffle 函数
std::random_shuffle 使用的是 rand 函数,
而 std::shuffle 使用的是更现代的随机数生成器(如 std::default_random_engine)。
std::shuffle 提供了更好的随机性和灵活性,因此推荐在C++11及以后的标准中使用 std::shuffle。
#include <iostream>
#include <algorithm> // 包含 random_shuffle
#include <vector>
#include <ctime>
#include <cstdlib> // 包含 srand 和 rand
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 设置随机种子
std::srand(std::time(0));
// 使用 random_shuffle 打乱 vector
std::random_shuffle(vec.begin(), vec.end());
// 输出打乱后的 vector
for (int i : vec) {
std::cout << i << " ";
}
return 0;
}
使用 std::shuffle
#include <iostream>
#include <algorithm> // 包含 shuffle
#include <vector>
#include <random> // 包含 default_random_engine
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 创建随机数生成器
std::random_device rd;
std::default_random_engine rng(rd());
// 使用 shuffle 打乱 vector
std::shuffle(vec.begin(), vec.end(), rng);
// 输出打乱后的 vector
for (int i : vec) {
std::cout << i << " ";
}
return 0;
}
查找
| 函数名 | 函数功能 | 函数声明 |
|------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| find | 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较.当匹配时,结束搜索,返回该元素的一个 InputIterator | template<class InIt, class T> InIt find(InIt first, InIt last, const T& val); |
| find_if | 使用输入的函数代替等于操作符,执行 find | template<class InIt, class Pred> InIt find_if(InIt first, InIt last, Pred pr); |
| count | 利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数 | template<class InIt, class Dist> size_t count(InIt first, InIt last, const T& val, Dist& n); |
| count_if | 利用输入的操作符,对标志范围内的元素进行操作,返回结果为 true 的个数 | template<class InIt, class Pred, class Dist> size_t count_if(InIt first, InIt last, Pred pr); |
| search | 给出两个范围,返回一个 ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向 last1,重载版本使用自定义的比较操作 | template<class FwdIt1, class FwdIt2> FwdIt1 search(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2); |
| | | template<class FwdIt1, class FwdIt2, class Pred> FwdIt1 search(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2, Pred pr); |
| search_n | 在指定范围内查找 val 出现 n 次的子序列。重载版本使用自定义的比较操作 | template<class FwdIt, class Dist, class T> FwdIt search_n(FwdIt first, FwdIt last, Dist n, const T& val); |
| | | template<class FwdIt, class Dist, class T, class Pred> FwdIt search_n(FwdIt first, FwdIt last, Dist n, const T& val, Pred pr); |
find()
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义一个函数,判断输入的整数是否大于等于3
bool func(int & v)
{
return v >= 3 ? true : false;
}
int main()
{
// 定义一个包含5个整数的数组
int data[5] = {1, 2, 3, 4, 5};
// 使用std::find查找数组中第一个值为4的元素
int *p = find(data, data + 5, 4);
if (p != data + 5)
printf("%d\n", *p); // 如果找到,打印该值
else
printf("find none\n"); // 如果未找到,打印"find none"
// 将数组转换为vector
vector<int> vi(data, data + 5);
// 使用std::find查找vector中第一个值为10的元素
vector<int>::iterator itr;
itr = find(vi.begin(), vi.end(), 10);
if (itr != vi.end())
cout << *itr << endl; // 如果找到,打印该值
else
cout << "find none" << endl; // 如果未找到,打印"find none"
// 使用std::find_if查找vector中第一个满足func条件的元素
itr = find_if(vi.begin(), vi.end(), func);
if (itr != vi.end())
cout << *itr << endl; // 如果找到,打印该值
else
cout << "find none" << endl; // 如果未找到,打印"find none"
return 0;
}
count
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// 定义一个函数,判断输入的整数是否大于10
bool func(int &v)
{
return v > 10 ? true : false;
}
int main()
{
// 定义一个包含8个整数的数组
int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};
// 使用std::count统计数组中值为10的元素个数
int mycount = count(myints, myints + 8, 10);
cout << "10 appears " << mycount << " times.\n";
// 将数组转换为vector
vector<int> myvector(myints, myints + 8);
// 使用std::count统计vector中值为20的元素个数
mycount = count(myvector.begin(), myvector.end(), 20);
cout << "20 appears " << mycount << " times.\n";
// 使用std::count_if统计vector中满足func条件的元素个数
mycount = count_if(myvector.begin(), myvector.end(), func);
cout << ">10 appears " << mycount << " times.\n";
return 0;
}
search
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// 定义一个模板函数,判断字符串s是否在容器cont中
template<typename Container>
bool inQuote(const Container& cont, const string& s)
{
// 使用std::search查找s在cont中的位置
return search(cont.begin(), cont.end(), s.begin(), s.end()) != cont.end();
}
int main()
{
// 定义一个字符串
string str = "why waste time learning, when ignorance is instantaneous?";
// 使用inQuote函数判断"learning"和"lemming"是否在字符串str中
cout << boolalpha << inQuote(str, "learning") << '\n'
<< inQuote(str, "lemming") << '\n';
// 将字符串转换为vector<char>
vector<char> vec(str.begin(), str.end());
// 使用inQuote函数判断"learning"和"lemming"是否在vector<char> vec中
cout << boolalpha << inQuote(vec, "learning") << '\n'
<< inQuote(vec, "lemming") << '\n';
return 0;
}
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
// 定义一个模板函数,判断容器c中是否存在连续count个值为v的元素
template <class Cont, class Size, class T>
bool consecutive_values(const Cont& c, Size count, const T& v)
{
// 使用std::search_n查找容器c中是否存在连续count个值为v的元素
return search_n(begin(c), end(c), count, v) != end(c);
}
int main()
{
// 定义一个字符数组
const char sequence[] = "1001010100010101001010101";
// 设置输出为布尔值形式
cout << boolalpha;
// 判断字符数组中是否存在连续4个'0'
cout << "Has 4 consecutive zeros: "
<< consecutive_values(sequence, 4, '0') << endl;
// 判断字符数组中是否存在连续3个'0'
cout << "Has 3 consecutive zeros: "
<< consecutive_values(sequence, 3, '0') << endl;
return 0;
}
删除与替换
| 函数名 | 函数功能 | 函数声明 |
|-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| copy | 复制序列 | template<class InIt, class OutIt> OutIt copy(InIt first, InIt last, OutIt x); |
| remove | 删除指定范围内所有等于指定元素的元素。注意,该函数不是真正删除函数。内置函数不适合使用 remove 和 remove_if 函数 | template<class FwdIt, class T> FwdIt remove(FwdIt first, FwdIt last, const T& val); |
| remove_if | 删除指定范围内输入操作结果为 true 的所有元素 | template<class FwdIt, class Pred> FwdIt remove_if(FwdIt first, FwdIt last, Pred pr); |
| remove_copy | 将所有不匹配元素复制到一个制定容器,返回 OutputIterator 指向被拷贝的末元素的下一个位置 | template<class InIt, class OutIt, class T> OutIt remove_copy(InIt first, InIt last, OutIt x, const T& val); |
| remove_copy_if | 将所有不匹配元素拷贝到一个指定容器 | template<class InIt, class OutIt, class Pred> OutIt remove_copy_if(InIt first, InIt last, OutIt x, Pred pr); |
| unique | 清除序列中重复元素,和 remove 类似,它也不能真正删除元素。重载版本使用自定义比较操作 | template<class FwdIt> FwdIt unique(FwdIt first, FwdIt last); |
| | | template<class FwdIt, class Pred> FwdIt unique(FwdIt first, FwdIt last, Pred pr); |
| unique_copy | 与 unique 类似,不过把结果输出到另一个容器 | template<class InIt, class OutIt> OutIt unique_copy(InIt first, InIt last, OutIt x); |
| | | template<class InIt, class OutIt, class Pred> OutIt unique_copy(InIt first, InIt last, OutIt x, Pred pr); |
copy()
//todo copy
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
using namespace std;
int main()
{
// 创建一个包含整数1到8的向量from
vector<int> from = {1, 2, 3, 4, 5, 6, 7, 8};
// 创建一个大小为10的向量to,初始值未定义
vector<int> to(10);
// 将from向量的内容复制到to向量中,从to的起始位置开始
copy(from.begin(), from.end(), to.begin());
// 调整to向量的大小,使其与from向量的大小相同
to.resize(from.size());
// 输出to向量的内容
cout << "to_vector contains: ";
// 使用copy算法将to向量的内容输出到标准输出,每个元素后跟一个空格
copy(to.begin(), to.end(), ostream_iterator<int>(cout, " "));
// 输出换行符
cout << '\n';
}
.remove
#include <algorithm>
#include <string>
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
// 定义一个整数数组
int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};
// 定义数组的起始和结束指针
int* pbegin = myints;
int* pend = myints + sizeof(myints) / sizeof(int);
// 使用std::remove移除数组中的值为20的元素
pend = remove(pbegin, pend, 20);
// 输出移除后的数组内容
cout << "range contains:";
for (int* p = pbegin; p != pend; ++p)
cout << ' ' << *p;
cout << '\n';
return 0;
}
int main2()
{
// 定义一个包含空格的字符串
string str1 = "Text with some spaces";
// 使用std::remove移除字符串中的空格
str1.erase(remove(str1.begin(), str1.end(), ' '), str1.end());
cout << str1 << '\n';
// 定义一个包含多种空白字符的字符串
string str2 = "Text\n with\tsome \t whitespaces\n\n";
// 使用std::remove_if移除字符串中的所有空白字符
str2.erase(remove_if(str2.begin(), str2.end(), [](char x) { return isspace(x); }), str2.end());
cout << str2 << '\n';
return 0;
}
unique 去除重复元素
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
// 创建一个包含重复元素的向量
vector<int> v = {1, 2, 3, 1, 2, 3, 3, 4, 5, 4, 5, 6, 7};
// 对向量进行排序,以便相同的元素相邻
sort(v.begin(), v.end());
// 排序后的向量为:1 1 2 2 3 3 3 4 4 5 5 6 7
// 使用unique算法移除相邻的重复元素,返回新的结束迭代器
auto last = unique(v.begin(), v.end());
// 此时向量v的内容为:1 2 3 4 5 6 7 x x x x x x,其中'x'是未定义的值
// 使用erase方法移除向量中从last到end之间的元素,即移除多余的未定义值
v.erase(last, v.end());
// 输出向量v的内容
for (int i : v)
cout << i << " ";
cout << "\n";
// 处理字符串中的连续空格
string s = "wanna go to space?";
// 使用unique算法移除连续的空格,自定义比较函数用于判断是否为连续空格
auto end = unique(s.begin(), s.end(),
[](char l, char r){
return isspace(l) && isspace(r) && l == r;
});
// 此时字符串s的内容为:"wanna go to space?xxxxxxxx",其中'x'是未定义的值
// 输出处理后的字符串,只输出到end迭代器之前的内容
cout << string(s.begin(), end) << '\n';
return 0;
}
排列组合
| 函数名 | 函数功能 | 函数声明 |
|-------------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| next_permutation | 取出当前范围内的排列,并重新排序为下一个排列。重载版本使用自定义的比较操作 | template<class BidIt> bool next_permutation(BidIt first, BidIt last); |
| | | template<class BidIt, class Pred> bool next_permutation(BidIt first, BidIt last, Pred pr); |
| prev_permutation | 取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回 false。重载版本使用自定义的比较操作 | template<class BidIt> bool prev_permutation(BidIt first, BidIt last); |
| | | template<class BidIt, class Pred> bool prev_permutation(BidIt first, BidIt last, Pred pr); |
next_permutation
#include <iostream>
#include <algorithm>
int main ()
{
// 定义一个包含三个整数的数组
int myints[] = {1, 2, 3};
// 对数组进行排序,确保初始顺序为升序
std::sort (myints, myints + 3);
// 输出提示信息
std::cout << "The 3! possible permutations with 3 elements:\n";
// 使用do-while循环来遍历所有可能的排列
do
{
// 输出当前排列
std::cout << myints[0] << ' '
<< myints[1] << ' '
<< myints[2] << '\n';
// 使用std::next_permutation生成下一个排列,直到所有排列都被生成
} while (std::next_permutation(myints, myints + 3));
// 输出循环结束后数组的最终状态
std::cout << "After loop: "
<< myints[0] << ' '
<< myints[1] << ' '
<< myints[2] << '\n';
return 0;
}
prev_permutation
#include <iostream>
#include <algorithm>
int main ()
{
// 定义一个包含三个整数的数组
int myints[] = {1, 2, 3};
// 对数组进行排序,确保初始顺序为升序
std::sort (myints, myints + 3);
// 输出提示信息
std::cout << "The 3! possible permutations with 3 elements:\n";
// 使用do-while循环来遍历所有可能的排列
do
{
// 输出当前排列
std::cout << myints[0] << ' '
<< myints[1] << ' '
<< myints[2] << '\n';
// 使用std::prev_permutation生成上一个排列,直到所有排列都被生成
} while (std::prev_permutation(myints, myints + 3));
// 输出循环结束后数组的最终状态
std::cout << "After loop: "
<< myints[0] << ' '
<< myints[1] << ' '
<< myints[2] << '\n';
return 0;
}
集合
| 函数名 | 函数功能 | 函数声明 |
|-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------|
| set_union | 构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作 | template<class InIt1, class InIt2, class OutIt> OutIt set_union(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x); |
| | | template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_union(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr); |
| set_difference | 构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作 | template<class InIt1, class InIt2, class OutIt> OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x); |
| | | template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr); |
| set_intersection| 构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作 | template<class InIt1, class InIt2, class OutIt> OutIt set_intersection(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x); |
| | | template<class InIt1, class InIt2, class OutIt, class Pred> OutIt set_intersection(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr); |
set_union 判断两个集合的并集
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
// 定义两个数组并初始化
int first[5] = {1, 2, 5, 7, 9};
int second[5] = {1, 2, 6, 8, 10};
// 创建一个vector,预留20个整数的空间
vector<int> vi(20);
vector<int>::iterator itr;
// 对两个数组进行排序
sort(first, first + 5);
sort(second, second + 5);
// 使用set_union函数将两个数组的并集存储到vector中
// set_union要求输入序列是有序的
itr = set_union(first, first + 5, second, second + 5, vi.begin());
// 调整vector的大小,使其只包含并集的元素
vi.resize(itr - vi.begin());
// 使用copy函数将vector中的元素输出到标准输出
copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " "));
return 0;
}
set_difference 判断两个集合的差集
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
// 定义两个数组,分别包含一些整数
int first[5] = {1, 2, 5, 7, 9};
int second[5] = {1, 2, 6, 7, 10};
// 创建一个大小为20的向量,用于存储结果
vector<int> vi(20);
// 定义一个迭代器,用于接收set_difference的结果
vector<int>::iterator itr;
// 对两个数组进行排序,确保它们是有序的
sort(first, first + 5);
sort(second, second + 5);
// 使用set_difference算法,找出first数组中有而second数组中没有的元素,并存储到vi向量中
// 返回值是一个迭代器,指向结果序列的结束位置
itr = set_difference(first, first + 5, second, second + 5, vi.begin());
// 调整vi向量的大小,使其只包含实际的结果元素
vi.resize(itr - vi.begin());
// 使用copy算法将结果输出到标准输出,每个元素之间用空格分隔
copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " "));
// 返回0,表示程序成功结束
return 0;
}
set_intersection 判断两个集合的交集
#include <iterator>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
// 定义两个数组并初始化
int first[5] = {1, 2, 5, 7, 9};
int second[5] = {1, 2, 6, 8, 10};
// 创建一个vector,预留20个整数的空间
vector<int> vi(20);
vector<int>::iterator itr;
// 对两个数组进行排序
sort(first, first + 5);
sort(second, second + 5);
// 使用set_intersection函数将两个数组的交集存储到vector中
// set_intersection要求输入序列是有序的
itr = set_intersection(first, first + 5, second, second + 5, vi.begin());
// 调整vector的大小,使其只包含交集的元素
vi.resize(itr - vi.begin());
// 使用copy函数将vector中的元素输出到标准输出
copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " "));
return 0;
}