C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ algorithm numeric

C++算法与泛型算法(algorithm、numeric)

作者:江南、董少

这篇文章主要介绍了C++算法与泛型算法(algorithm、numeric),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

本文包括的算法有:

一、算法简介

大多数算法在头文件algorithm中。标准库还在头文件numeric中定义了一组数值泛型算法
算法是如何工作的:

二、泛型算法

三、只读算法

find()

//判断value在vec中是否存在,因为find如果失败返回的是参数2.所以可以用来判断是否查找成功
 
vector<int> vec{ 1,2,3};
int value = 2;
auto result=find(vec.cbegin(),vec.cend(), value);
cout << "The value " << value << (result == vec.cend()
 ? "is not present" : "is present") << endl;
vector<string> vec{ "A","B","C" };
auto result=find(vec.cbegin(),vec.cend(), "B");
cout << "The B "<< (result == vec.cend()
 ? "is not present" : "is present") << endl;

对数组的操作:可以用内置函数begin()、end()作为数组的迭代器,也可以用指针作为迭代器

int arr[] = { 1,2,3,4,5 };
int val = 4;
int* result = find(begin(arr), end(arr), val);
if (result != end(arr)) {
 cout << "find succcess,value is:"<< *result<< endl;
}
int arr[] = { 1,2,3,4,5 };
int value = 3;
auto result = find(arr + 1, arr + 3, value);
cout << "The value "<<value<<((result == arr + 3)
	?" is not present":"is present")<< endl;

count()

list<int> li{ 1,2,3,66,66,66,100 };
cout <<"The 66 count is:" 
	<<count(li.cbegin(),li.cend(),66)<< endl;

accumulate()

//计算li元素的和,和的初始值为0
list<int> li{ 1,2,3 };
cout <<"The sum is:" <<accumulate(li.cbegin(),li.cend(),0)<< endl; //6

使用string时,必须显示地调用,不能够直接使用字符串,因为这样会被accumulate函数认为是一个const char*对象而出错

//正确
ist<string> li{"A","B","C"};
cout <<accumulate(li.cbegin(),li.cend(),string("String:"))<< endl; //String:ABC
//错误
list<string> li{"A","B","C"};
cout <<accumulate(li.cbegin(),li.cend(),"String:")<< endl;
//正确
list<string> li{"A","B","C"};
string s = "String:";
cout <<accumulate(li.cbegin(),li.cend(), s)<< endl;

附加:如果想要进行别的运行,例如乘、除等,可以使用参数4.例如下面是对一个数组内的元素进行乘操作(备注:初始化不要填0,否则结果就为0)

int *p = new int[4] {1, 2, 3, 4};
cout << accumulate(p, p + 4, 1,multiplies<int>()) << endl; //24

equal()

vector<int> vec1{ 1,2};
vector<int> vec2{ 1,2,3};
vector<int> vec3{ 1,2,3,4};
vector<int> vec4{ 1,2,3,4 };
 
cout << equal(vec1.cbegin(),vec1.cend(), vec4.cbegin())<< endl; //1
cout << equal(vec2.cbegin(), vec2.cend(), vec4.cbegin()) << endl; //1
cout << equal(vec3.cbegin(), vec3.cend(), vec4.cbegin()) << endl; //1
vector<int> vec1{ 2,3};
vector<int> vec2{ 1,2,3,4 };
 
cout << equal(vec1.cbegin(),vec1.cend(), vec2.cbegin())<< endl; //0
vector<string> vec1{ "A","B"};
vector<string> vec2{ "B" };
vector<const char*> vec3{ "A","B","C" };
 
cout << equal(vec1.cbegin(), vec1.cend(), vec3.cbegin()) << endl; //1
cout << equal(vec2.cbegin(), vec2.cend(), vec3.cbegin())<< endl; //0

四、写算法

可以读写容器内的元素,但不可以改变容器的大小。因此操作时要注意容器的大小(例如不能对空容器操作)

因为会改变值,所以不能使用只读迭代器(cbegin()、cend())

fill()

vector<int> vec{ 1,2,3,4,5 };
fill(vec.begin(), vec.end(), 0);//将vec全部置为0
for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;
vector<int> vec{ 1,2,3,4,5,6 };
fill(vec.begin(), vec.begin()+vec.size()/2, 66); //将vec的前半部分元素变为66
 
for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;

fill_n()

vector<int> vec{ 1,2,3,4,5,6 };
 
fill_n(vec.begin(), 3, 66); //将vec的前3个元素变为66
for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;
 
fill_n(vec.begin(), vec.size(), 66); //将vec全部变为66
for (auto v = vec.cbegin(); v != vec.cend(); v++)
	cout << *v << endl;
//下面代码不会出错,但是也不会有效果,因为vec是空向量
 
vector<int> vec;
fill_n(vec.begin(), vec.size(), 66);
for (auto v = vec.cbegin(); v != vec.cend(); v++) //不打印任何信息
	cout << *v << endl;

back_inserter()

vector<int> vec; //空容器
 
auto it = back_inserter(vec); //返回vec的第一个迭代器
*it = 42; //此时vec有了一个元素,值为42

现在我们可以使用fill_n来给一个空容器赋值:在每次迭代中,back_inserter返回迭代器,因此每次赋值都会在vec上调用push_back,因此fill_n就能够操作了。下面是在vec的末尾添加10个新的元素

vector<int> vec;
fill_n(back_inserter(vec), 10, 0);//通过back_inserter创建一个插入迭代器,然后可以向vec添加元素了
for (auto v = vec.cbegin(); v != vec.cend(); v++) //打印10个0
	cout << *v << endl;

copy()

int arr1[] = { 1,2,3 };
int arr2[sizeof(arr1)/sizeof(*arr1)];
 
auto ret = copy(begin(arr1), end(arr1), arr2); //将数组1拷贝给数组2。ret为arr2数组最后元素的下一个位置
 
for (auto i = 0; i < sizeof(arr2) / sizeof(*arr2); i++) {
 cout << arr2[i]<< endl;
}

copy_backward

replace()

vector<int> vec{ 1,0,0,0,5 };
replace(vec.begin(), vec.end(), 0,66); //将vec中为0的全部替换为66
 
for (auto v = vec.cbegin(); v != vec.cend(); v++) {
	cout << *v << endl;
}

replace_copy()

vector<int> vec{ 1,0,0,0,5 };
vector<int> vec2;
 
replace_copy(vec.begin(), vec.end(),back_inserter(vec2), 0,66); //vec的元素保持不变,vec2为替换后的值
	
for (auto v = vec2.cbegin(); v != vec2.cend(); v++) {
 cout << *v << endl;
}

next_permutation()

//函数原型
#include <algorithm>
bool next_permutation(iterator start,iterator end)

演示案例:下面的程序每调用一次next_permutation就会对我们制定的迭代区间进行一次排列,直到得出全部排列之后,返回false

int *p = new int[3] {1, 2, 3};
do {
 for (int i = 0; i < 3; ++i){
  cout << p[i];
 }
 cout << endl;
} while (next_permutation(p, p + 3));

prev_permutation()

五、重排元素算法

sort()、unqie()、stable_sort()

因为会改变值,所以不能使用只读迭代器(cbegin()、cend())

sort()

vector<int> vec{ 1,4,2,8,4,1 };
sort(vec.begin(), vec.end()); //将vec的值从小到大排序
 
for (auto v = vec.cbegin(); v != vec.cend(); v++) {
 cout << *v << endl;
}

unique()

vector<int> vec{ 1,1,2,3,4,4,4,5,1 };
auto end_unique=unique(vec.begin(), vec.end());
 
//for循环时使用unique的返回值,如果使用vec.cend(),那么会打印后面没有元素位置的乱值
for (auto v = vec.cbegin(); v != end_unique; v++) { 
	cout << *v << endl;
}

stable_sort()

vector<int> vec{ 1,10,2,100,4,1 };
stable_sort(vec.begin(), vec.end());
 
//1,1,2,4,10,100
for (auto v = vec.cbegin(); v != vec.cend(); v++) {
 cout << *v << endl;
}

六、向算法传递函数和lambda表达式

注意事项:

向算法传递函数或者lambda表达式时要注意。该算法支持调用一元谓词(参数)还是多元谓词(参数)

例如:find_if的第3个参数传递的函数/lambda只接受一个参数,如果是两个参数的函数或lambda,那么就不能调用(后面会介绍bind函数解决这个问题)

sort()

bool isMin(const int &s1, const int & s2) {
 return s1 < s2;
}
 
bool isMax(const int &s1, const int & s2) {
 return s1 > s2;
}
 
vector<int> vec{1,2,3,4,5};
sort(vec.begin(), vec.end(), isMin); //从小到大排序
sort(vec.begin(), vec.end(), isMax); //从大到小排序
 
//使用lambda表达式
sort(vec.begin(), vec.end(),
 [](const int &a, const int &b) {return a < b; });//从小到大排序
sort(vec.begin(), vec.end(), 
 [](const int &a, const int &b) {return a > b; });//从大到小排序

stable_sort()

//按照长度排序,长度相同的按照字典排序
bool isShorter(const string &s1, const string & s2) {
	return s1.size() < s2.size();
}
 
vector<string> vec{"fox","jumps","over","quick","res","slow","the","turtle"};
stable_sort(vec.begin(), vec.end(), isShorter);
 
for (auto v = vec.cbegin(); v != vec.cend(); v++) {
	cout << *v << endl;
}

find_if()

vector<int> vec{ 1,2,3,4,5 };
int sz = 4;
 
//在vec中寻找比sz大的数
auto wc=find_if(vec.begin(), vec.end(), 
 [sz](const int &a) {return a > sz; }); //查找比sz大的
auto wc2=find_if(vec.begin(), vec.end(), 
		[sz](const int &a) {return a < sz; }); //查找比sz小的
 
cout << *wc << endl; //5
cout << *wc2 << endl; //3

for_each()

vector<int> vec{ 1,2,3,4,5 };
 
for_each(vec.begin(), vec.end(), 
 [](const int&s) {cout << s << " "; });
cout << endl;
vector<string> vec{ "ABC","AB","A","sd" };
 
for_each(vec.begin(), vec.end(), 
 [](const string&s) {cout << s << " "; });
cout << endl;

transform()

vector<int> vec{ -1,-2,-3,4 };
//将vec的数全部取绝对值
transform(vec.begin(), vec.end(), vec.begin(),
		[](int i) {return i < 0 ? -i : i; });
 
for (auto v = vec.begin() ; v != vec.end(); ++v)
	cout <<*v << endl;

到此这篇关于C++算法与泛型算法(algorithm、numeric)的文章就介绍到这了,更多相关C++ algorithm numeric内容请搜素脚本之家以前的文章或下面相关文章,希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文