STL算法-03查找算法

常用查找算法

  1. find()
  2. find_if()
  3. search_n()
  4. search()
  5. find_end()
  6. first_first_of()
  7. adjacent_find()

find()find_if()

  1. find()find_if()是线性查找,查找速度较慢。查找的结果是迭代器。
  2. 如果是已序区间,可以使用已序区间查找算法:
    1. binary_search()
    2. includes()
    3. lower_bound()
    4. upper_bound()
  3. 关联式容器有等效的成员函数find(),时间复杂度为对数复杂度 l o g ( n ) log(n) log(n).
  4. string有等效的成员函数find().

find()代码示例

#include <iostream>
#include <algorithm>
#include <list>

using namespace std;

int main()
{
	list<int> ilist;
	for (int i = 1; i <= 9; ++i)
		ilist.insert(ilist.end(), i);
	for (int i = 1; i <= 9; ++i)
		ilist.insert(ilist.end(), i);

	for (list<int>::iterator iter = ilist.begin();
		iter != ilist.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	list<int>::iterator pos1;
	pos1 = find(ilist.begin(), ilist.end(), 4);

	list<int>::iterator pos2;
	if (pos1 != ilist.end())
	{
		pos2 = find(++pos1, ilist.end(), 4);
	}

	if (pos1 != ilist.end() && pos2 != ilist.end())
	{
		--pos1;
		++pos2;
		for (list<int>::iterator iter = pos1; iter != pos2; ++iter)
			cout << *iter << ' ';
	}
	return 0;
}

find_if()代码示例

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>

using namespace std;

int main()
{
	vector<int> ivec;
	vector<int>::iterator pos;

	for (int i = 1; i <= 9; ++i)
		ivec.push_back(i);

	for (vector<int>::iterator iter = ivec.begin();
		iter != ivec.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	pos = find_if(ivec.begin(), ivec.end(), bind2nd(greater<int>(), 3));
	cout << *pos << endl;

	// 第一个能被3整除的数
	pos = find_if(ivec.begin(), ivec.end(), not1(bind2nd(modulus<int>(), 3)));
	cout << *pos << endl;

	return 0;
}

关联式容器成员函数find()

#include <iostream>
#include <set>

using namespace std;

int main()
{
	set<int> iset;
	iset.insert(43);
	iset.insert(78);
	iset.insert(-1);
	iset.insert(124);

	for (set<int>::iterator iter = iset.begin();
		iter != iset.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	set<int>::iterator pos;
	pos = iset.find(78);
	if (pos != iset.end())
		cout << "找到了:" << *pos << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

string的成员函数find()

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("AnnaBelle");
	string::size_type pos = s.find("Bell");
	if (pos != string::npos)
		cout << "找到了:" << pos << endl;
	else
		cout << "没找到!" << endl;
	
	pos = s.find("bell");
	if (pos != string::npos)
		cout << "找到了:" << pos << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

search_n()

  1. search_n(b, e, c, v):查找连续的n个值;[b, e)迭代器,c个数,v数值value
  2. search_n(b, e, c, v, p)p谓词。
  3. 该算法的第二种形式本应为:search_n_if(b, e, c, p),但是错误。

代码示例

#include <iostream>
#include <deque>
#include <algorithm>
#include <functional>

using namespace std;

int main()
{
	deque<int> ideq;
	for (int i = 1; i <= 9; ++i)
	{
		if (i == 3)
		{
			ideq.push_back(3);
			ideq.push_back(3);
			ideq.push_back(3);
			ideq.push_back(3);
		}
		else
			ideq.push_back(i);
	}
	for (deque<int>::iterator iter = ideq.begin();
		iter != ideq.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	deque<int>::iterator pos;
	pos = search_n(ideq.begin(), ideq.end(), 4, 3);
	if (pos != ideq.end())
		//cout << "找到连续的4个3:" << *pos << endl;
		//                               begin()迭代器与pos迭代器之间的距离(差)
		cout << "找到连续的4个3,序号的位置:" << distance(ideq.begin(), pos)+1 << endl;
	else
		cout << "没找到!" << endl;

	//                                             必须为二元谓词
	pos = search_n(ideq.begin(), ideq.end(), 3, 6, greater<int>());
	//pos = search_n_if(ideq.begin(), ideq.end(), 3, bind2nd(greater<int>(), 6)); //错误写法
	if (pos != ideq.end())
		cout << "找到了连续的3个大于6的数,start with " << distance(ideq.begin(), pos) << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

search()find_end()

  1. search()find_end()是一对函数,顺序和逆序查找。

简单代码示例

#include <iostream>
#include <deque>
#include <list>
#include <algorithm>

using namespace std;

int main()
{
	deque<int> ideq;
	list<int> ilist;

	for (int i = 1; i <= 7; ++i)
		ideq.insert(ideq.end(), i);
	for (int i = 1; i <= 7; ++i)
		ideq.insert(ideq.end(), i);
	
	for (int i = 3; i <= 6; ++i)
		ilist.insert(ilist.end(), i);

	for (deque<int>::iterator iter = ideq.begin();
		iter != ideq.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	for (list<int>::iterator iter = ilist.begin();
		iter != ilist.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	deque<int>::iterator pos;
	pos = search(ideq.begin(), ideq.end(), ilist.begin(), ilist.end());
	/*if (pos != ideq.end())
		cout << "找到了!位置:" << distance(ideq.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;

	++pos;
	pos = search(pos, ideq.end(), ilist.begin(), ilist.end());
	if (pos != ideq.end())
		cout << "找到了!位置:" << distance(ideq.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;*/

	while (pos != ideq.end())
	{
		cout << "找到了!位置:" << distance(ideq.begin(), pos) + 1 << endl;
		
		++pos;
		pos = search(pos, ideq.end(), ilist.begin(), ilist.end());		
	}

	cout << "使用find_end()进行查找:" << endl;
	pos = find_end(ideq.begin(), ideq.end(), ilist.begin(), ilist.end());
	if (pos != ideq.begin())
		cout << "找到了!位置:" << distance(ideq.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

使用二元谓词代码示例

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 二元谓词
// even=true检查是否为偶数,even=false检查是否为奇数
bool checkEven(int elem, bool even)
{
	if (even)
		return elem % 2 == 0;
	else
		return elem % 2 == 1;
}

int main()
{
	vector<int> ivec;
	for (int i = 1; i <= 9; ++i)
		ivec.push_back(i);
	ivec.push_back(10); // 2
	ivec.push_back(20); // 2
	ivec.push_back(30); // 2
	for (vector<int>::iterator iter = ivec.begin();
		iter != ivec.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	//bool checkEvenArgs[3] = { true, false, true }; // 1
	//bool checkEvenArgs[3] = { true, true, true }; // 2-1
	bool checkEvenArgs[3] = { false, true, true }; // 2-2
	vector<int>::iterator pos;
	pos = search(ivec.begin(), ivec.end(), checkEvenArgs, checkEvenArgs + 3, checkEven);
	if (pos != ivec.end())
		cout << "找到了!位置:" << distance(ivec.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

find_first_of()

  1. find_first_of(b, e, sb, se)
    1. 在迭代器[b,e)中查找迭代器[sb, se)中的任意一个元素,返回能找到的迭代器[sb, se)中能找到的第一个元素的下标。
  2. find_first_of(b, e, sb, se, bp)
  3. 使用逆向迭代器,没有find_last_of()算法

string查找函数和STL查找算法的比较

string函数STL算法
find()find()
rfind()find()+逆向迭代器
find()search()
rfind()find_end()
find_first_of()find_first_of()
find_last_of()find_first_of()+逆向迭代器

代码示例

#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
	vector<int> ivec;
	list<int> searchList;

	for (int i = 1; i <= 9; ++i)
		ivec.push_back(i);
	for (vector<int>::iterator iter = ivec.begin();
		iter != ivec.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;
	searchList.push_back(3);
	searchList.push_back(6);
	searchList.push_back(9);

	vector<int>::iterator pos;
	pos =find_first_of(ivec.begin(), ivec.end(), searchList.begin(), searchList.end());
	if (pos != ivec.end())
		cout << "找到了!位置:" << distance(ivec.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;

	vector<int>::reverse_iterator rpos;
	rpos = find_first_of(ivec.rbegin(), ivec.rend(), searchList.begin(), searchList.end());
	cout << "找到了!位置:" << distance(ivec.begin(), rpos.base()) << endl;

	string numerics("0123456789");
	//string name("r2d3k");
	//string name("ra8d3k");
	string name("ra8d3wp6k");
	string::size_type p = name.find_first_of(numerics);
	if (p != string::npos)
		cout << "找到了,下标:" << p << endl;
	else
		cout << "没找到!" << endl;

	p = name.find_last_of(numerics);
	if (p != string::npos)
		cout << "找到了,下标:" << p << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

adjacent_find()

  1. adjacent_find(b, e):搜索序列中两个连续相等的元素,用 == 运算符来比较连续的一对元素,返回的迭代器指向前两个相等元素中的第一个。如果没有一对相等的元素,这个算法返回这个序列的结束迭代器。
  2. adjacent_find(b, e, p):谓词p.
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool doubled(int elem1, int elem2)
{
	return elem1 * 2 == elem2;
}

int main()
{
	vector<int> ivec;
	ivec.push_back(1);
	ivec.push_back(3);
	ivec.push_back(2); //6
	ivec.push_back(4); // 6
	ivec.push_back(5);
	ivec.push_back(5);
	ivec.push_back(0);

	for (vector<int>::iterator iter = ivec.begin();
		iter != ivec.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	vector<int>::iterator pos;
	pos = adjacent_find(ivec.begin(), ivec.end());
	if (pos != ivec.end())
		cout << "找到了!位置:" << distance(ivec.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;

	pos = adjacent_find(ivec.begin(), ivec.end(), doubled);
	if (pos != ivec.end())
		cout << "找到了!位置:" << distance(ivec.begin(), pos) + 1 << endl;
	else
		cout << "没找到!" << endl;

	return 0;
}

已序区间查找算法

binary_search()includes()

  1. binary_search(b, e, v):只返回bool查找结果。
  2. binary_search(b, e, v, p)
  3. includes(b, e, sb, se)
  4. includes(b, e, sb, se, p)
  5. 查找必须要求已排序。
  6. 查找可以不连续,只要有就可以。
  7. 谓词p可以指定排序规则。

代码示例

#include <iostream>
#include <list>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	list<int> ilist;
	vector<int> search;

	for (int i = 1; i <= 9; ++i)
		ilist.insert(ilist.end(), i);

	search.push_back(3);
	search.push_back(4);
	search.push_back(7); //45

	for (list<int>::iterator iter = ilist.begin();
		iter != ilist.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	if (binary_search(ilist.begin(), ilist.end(), 5))
		cout << "找到了!" << endl;
	else
		cout << "没找到!" << endl;

	if (includes(ilist.begin(), ilist.end(), search.begin(), search.end()))
		cout << "都有,都找到了" << endl;
	else
		cout << "没找到!" << endl;
	
	return 0;
}

lower_bound()

upper_bound()

equal_range()

代码示例

#include <iostream>
#include <list>
#include <algorithm>

using namespace std;

int main()
{
	list<int> ilist;

	for (int i = 1; i <= 9; ++i)
		ilist.insert(ilist.end(), i);
	for (int i = 1; i <= 9; ++i)
		ilist.insert(ilist.end(), i);
	ilist.push_back(5);
	ilist.push_back(5);
	ilist.push_back(5);
	ilist.sort();
	
	for (list<int>::iterator iter = ilist.begin();
		iter != ilist.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	list<int>::iterator pos1, pos2;
	pos1 = lower_bound(ilist.begin(), ilist.end(), 5);
	pos2 = upper_bound(ilist.begin(), ilist.end(), 5);

	cout << "第一个5的位置:" << distance(ilist.begin(), pos1) + 1 << endl;
	cout << "大于5的第一个位置:" << distance(ilist.begin(), pos2) + 1 << endl;
	
	ilist.insert(lower_bound(ilist.begin(), ilist.end(), 5), 5);
	ilist.insert(upper_bound(ilist.begin(), ilist.end(), 5), 5);
	for (list<int>::iterator iter = ilist.begin();
		iter != ilist.end(); ++iter)
		cout << *iter << ' ';
	cout << endl;

	pair<list<int>::iterator, list<int>::iterator> range;
	range = equal_range(ilist.begin(), ilist.end(), 5);
	cout << distance(ilist.begin(), range.first) + 1 << endl;
	cout << distance(ilist.begin(), range.second) + 1 << endl;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值