泛型算法与容器的关系



1.前言


c++中的容器支持插入删除操作,支持获取第一个元素的迭代器和超过元素末端的下一迭代器操作......但是却不支持获取指定元素操作,比较操作,排序操作......因为这些操作都是和算法有关的,在C++中将它们独立出来,说明算法和具体的容器和具体的数据类型无关,只和自身的元素相关。比如find函数,用于查找指定的值,看下面两段代码:


vector<int> vect;
//往vect添加元素
vector<int>::iterator iter=find(vect.begin(),vect,end(),search_value);


list<int> lis;
//添加元素
list<int>::iterator iter=find(lis.begin(),lis.end(),search_value);

int a[5]={1,2,3,4,5};
int *result=find(a,a+5,search_value);

我们可以对于find函数来说,它对于容器的类型和数据类型都没有要求,即它只与自身的算法实现有关,和容器类型无关。除了迭代器之外,我们可以发现,指针也可以用于find函数的实参。所以对find函数来说只有几个要求:

①、数据类型必须是可以比较的,这样才可以判断是否是所查找的值。

②、必须给定一段范围,必须知道从哪里开始从哪里结束。

③、如果找到该值,就返回指向该值的指针或者迭代器,否则返回第二个参数即最后一个元素的下一个元素的地址。


在C++中提供了泛型算法,它包含在algorithm头文件中,以及一个泛化的算数算法,它包含在numeric头文件中。



2、只读算法




只读算法只会读取范围内的元素,而不对范围内的元素进行任何操作。前面的find函数就是一个例子,另一个就是accumulate函数,定义在numeric头文件中,它使用数据类型的加法操作进行将某段元素范围的元素相加。考虑下面的代码:

vecotr<int> vectInt;
vector<string> vectString;

int sum=accumulate(vectInt.begin(),vectInt.end(),0);

string result=accumulate(vectString.begin(),vectString.end(),string(""));

上述尝试对int和string元素进行相加操作,对于sum的值,它是以0为起始值,并把vectInt标记的元素范围内所有值的相加。对于accumulate来说,它并不知道要添加的元素的类型是什么,因此它是通过第三个参数来判断执行加操作符的意义的。比如result的结果则是,获取了一端拼接起来的字符串。注意这里不能替换为字符串字面值,因为字符串字面值是const char*类型,这样会导致编译错误。


在numeric头文件,还有很多find系列的函数,比如find_fisrt_of();此函数接受四个参数,分别标志两段数据范围,它的作用用于查找在这两段标志的区间里面重合的元素,如果找到了就返回第一段范围内第一个重合元素的迭代器,否则就返回第一段范围内最后一个元素的下一个元素的迭代器。看如下代码:

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

int main()
{
	
	vector<string> vect;
	vect.push_back("harden");
	vect.push_back("james");
	vect.push_back("howard");
	vect.push_back("harden");
	vect.push_back("wade");


	vector<string> vect1(vect);
	vect1.erase(--vect1.end());

	vector<string>::iterator it = vect.begin();
	int count = 0;

	while ((it = find_first_of(it, vect.end(), vect1.begin(), vect1.end())) != vect.end())
	{
		count++;
		it++;
	}
	cout << count << endl;
	system("pause");
	return 0;
}

上述代码会打印出4,因为在第一段范围内,每次查找到第一个元素就会缩小到下一个元素,这样就把第一段范围内所有的与第二段范围重合的元素查找出来了。





3、利用算法排序元素



C++提供了排序算法,可用于排序容器内的元素,比如sort,此方法有两个版本,一个是接受一对迭代器作为实参(此版本的方法默认是使用<比较符比较对象),另外一个是除了一对迭代器之外,还接受一个函数名称。对该函数是由要求的,比如如果排序的对象是vector<int>型,则该函数的返回值必须是bool,形参必须是两个int型对象的引用。

注意,任何算法都不会删除或修改添加容器元素的元素数据。因此C++还提供了一个unique算法,可以将所有容器中出现多次的内容都排到容器末端,并且返回指向第一个相同元素的迭代器。通过它,我们就可以避免重复对容器中相同的元素进行操作。

看下面的代码:

	vector<string> vect;
	vect.push_back("harden");
	vect.push_back("james");
	vect.push_back("howard");
	vect.push_back("harden");
	vect.push_back("wade");
/*
	对容器内元素进行排序
	*/
	vect.push_back("james");
	//sort 元素会对元素内的元素进行<排序
	sort(vect.begin(), vect.end());
	
	cout << "输出从小到大排序后的内容:";
	for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it)
	{
		cout << *it<<" ";
	}
	cout << endl;


	//此函数会将容器内的元素的相同元素都排到容器的末端,然后返回指向第一个相同元素的迭代器。即在此迭代器之前的元素都是唯一的
	vector<string>::iterator uniqu_end = unique(vect.begin(), vect.end());
	cout<<"输出不包含相同元素的容器内容:";
	for (vector<string>::iterator it = vect.begin(); it < uniqu_end; ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

	//可使用erase将相同元素删掉。
	vect.erase(uniqu_end, vect.end());
	cout << "输出删除元素后的内容:";
	for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

	//使用sort的时候,也可以自带排序算法函数
	sort(vect.begin(), vect.end(), isLonger);
	cout << "输出从大到小排序元素后的内容:";
	for (vector<string>::iterator it = vect.begin(); it < vect.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

isLonger函数如下:

bool isLonger(string &one, string &two)
{
	return one > two;
}


输出结果:








4.迭代器综述

我们一般接触的迭代器都是正向迭代器,其实C++还提供了正向迭代器,iostream迭代器,插入迭代器。如下:






有关算法是不和容器捆绑的,除了前面提到的算法之外,还有很多不常用的算法,希望读者有兴趣的多去了解。



---------文章写自:HyHarden---------

--------博客地址:http://blog.csdn.net/qq_25722767-----------






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值