STL演算法-03查詢演算法
阿新 • • 發佈:2020-12-16
常用查詢演算法
find()
find_if()
search_n()
search()
find_end()
first_first_of()
adjacent_find()
find()
和find_if()
find()
和find_if()
是線性查詢,查詢速度較慢。查詢的結果是迭代器。- 如果是已序區間,可以使用已序區間查詢演算法:
binary_search()
includes()
lower_bound()
upper_bound()
- 關聯式容器有等效的成員函式
find()
,時間複雜度為對數複雜度 l o g ( n ) log(n) log(n). 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()
search_n(b, e, c, v)
:查詢連續的n
個值;[b, e)
迭代器,c
個數,v
數值value
。search_n(b, e, c, v, p)
:p
謂詞。- 該演算法的第二種形式本應為:
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()
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()
find_first_of(b, e, sb, se)
- 在迭代器
[b,e)
中查詢迭代器[sb, se)
中的任意一個元素,返回能找到的迭代器[sb, se)
中能找到的第一個元素的下標。
- 在迭代器
find_first_of(b, e, sb, se, bp)
- 使用逆向迭代器,沒有
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()
adjacent_find(b, e)
:搜尋序列中兩個連續相等的元素,用==
運算子來比較連續的一對元素,返回的迭代器指向前兩個相等元素中的第一個。如果沒有一對相等的元素,這個演算法返回這個序列的結束迭代器。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()
binary_search(b, e, v)
:只返回bool
查詢結果。binary_search(b, e, v, p)
includes(b, e, sb, se)
includes(b, e, sb, se, p)
- 查詢必須要求已排序。
- 查詢可以不連續,只要有就可以。
- 謂詞
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;
}