1. 程式人生 > 其它 >STL演算法-03查詢演算法

STL演算法-03查詢演算法

技術標籤:STL學習c++演算法stl

常用查詢演算法

  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;
}