您的位置:首页 > 编程语言 > C语言/C++

C++ STL Algorithm

2009-11-09 15:04 176 查看
1. 复制一个范围的元素 copy()

Copies the elements in the range [first,last) into a range beginning at result.

应用:接收标准输入保存到容器;输出容器内的元素。

copy(istream_iterator<T>(cin), istream_iterator<T>(), back_insert_iterator< vector<int> >(num))

copy(A.begin(), A.end(), ostream_iterator(cout, " "));

//From: http://www.cnblogs.com/cutepig/archive/2007/07/15/818957.html #include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
void main(void)
{
typedef vector<int>    int_vector;
typedef istream_iterator<int>    istream_itr;
typedef ostream_iterator<int>    ostream_itr;
typedef back_insert_iterator< int_vector > back_ins_itr;
// STL中的vector容器
int_vector num;
// 从标准输入设备读入整数,
// 直到输入的是非整型数据为止
copy(istream_itr(cin), istream_itr(), back_ins_itr(num));
// STL中的排序算法
sort(num.begin(), num.end());
// 将排序结果输出到标准输出设备
copy(num.begin(), num.end(), ostream_itr(cout, "/n"));
}


2. 从最后的元素开始复制 copy_backward()

http://www.cplusplus.com/reference/algorithm/copy_backward/

Copy range of elements backwards

Copies the elements in the range [first,last) into a range whose last element is result. The function begins by copying *(last-1) into *(result-1), and then follows backwards by the elements preceeding these, until first is reached (and including it).

The behavior of this function template is equivalent to:

template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 copy_backward ( BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result )
{
while (last!=first) *(--result) = *(--last);
return result;
}


// copy_backward example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
vector<int> myvector;
vector<int>::iterator it;
// set some values:
for (int i=1; i<=5; i++)
myvector.push_back(i*10);          // myvector: 10 20 30 40 50
myvector.resize(myvector.size()+3);  // allocate space for 3 more elements
copy_backward ( myvector.begin(), myvector.begin()+5, myvector.end() );
cout << "myvector contains:";
for (it=myvector.begin(); it!=myvector.end(); ++it)
cout << " " << *it;
cout << endl;
return 0;
}
/*
Output:
myvector contains: 10 20 30 10 20 30 40 50
*/


3. 容器元素累加 accumulate()

accumulate(numbers,numbers+3,init);

// accumulate example
#include <iostream>
#include <functional>
#include <numeric>
using namespace std;
int myfunction (int x, int y) {return x+2*y;}
struct myclass {
int operator()(int x, int y) {return x+3*y;}
} myobject;
int main () {
int init = 100;
int numbers[] = {10,20,30};
cout << "using default accumulate: ";
cout << accumulate(numbers,numbers+3,init);
cout << endl;
cout << "using functional's minus: ";
cout << accumulate (numbers, numbers+3, init, minus<int>() );
cout << endl;
cout << "using custom function: ";
cout << accumulate (numbers, numbers+3, init, myfunction );
cout << endl;
cout << "using custom object: ";
cout << accumulate (numbers, numbers+3, init, myobject );
cout << endl;
return 0;
}
/*
output:
using default accumulate: 160
using functional's minus: 40
using custom function: 220
using custom object: 280
*/


Note: 第3个参数的类型会影响返回的结果,如果作浮点型的运算,第3个参数应该为0.0而不是0。

4. 将函数应用到一个范围内的所有元素 for_each()

Applies function f to each of the elements in the range [first,last):

http://www.cplusplus.com/reference/algorithm/for_each/

The behavior of this template function is equivalent to:

template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f)
{
for ( ; first!=last; ++first ) f(*first);
return f;
}


/*Return value
The same as f.*/
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void myfunction (int i) {
cout << " " << i;
}
struct myclass {
void operator() (int i) {cout << " " << i;}
} myobject;
int main () {
vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myfunction);
// or:
cout << "/nmyvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
cout << endl;
return 0;
}

/*
Output:
myvector contains: 10 20 30
myvector contains: 10 20 30
Complexity
Linear: Applies f once to each element.
*/


5. 范围内元素替换 replace()

http://www.cplusplus.com/reference/algorithm/replace/

// replace algorithm example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99
cout << "myvector contains:";
for (vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
cout << " " << *it;
cout << endl;

return 0;
}
/*
Output:
myvector contains: 10 99 30 30 99 10 10 99
*/


6. 从范围内删除指定值 remove()

http://www.cplusplus.com/reference/algorithm/remove/

从实现来看与erase()不同,通用算法中的remove()也与容器list的成员函数remove()不同,通用算法中的remove()并没有容器中删除东西而是把非指定的值位置提前替换掉指定值占用的位置。

template < class ForwardIterator, class T >
ForwardIterator remove ( ForwardIterator first, ForwardIterator last, const T& value )
{
ForwardIterator result = first;
for ( ; first != last; ++first)
if (!(*first == value)) *result++ = *first;
return result;
}


// remove algorithm example
#include <iostream>
#include <algorithm>
using namespace std;
int main () {
int myints[] = {10,20,30,30,20,10,10,20};      // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints;                          // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^                       ^
pend = remove (pbegin, pend, 20);              // 10 30 30 10 10 10 10 20
// ^              ^
cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
cout << " " << *p;
cout << endl;
cout << "range contains:";
pend = myints+sizeof(myints)/sizeof(int);
for (int* pt=pbegin; pt!=pend; ++pt)
cout << " " << *pt;

return 0;
}


应用函数而不具体指定值来判断要删除的元素 remove_if()

http://www.cplusplus.com/reference/algorithm/remove_if/

// remove_if example
#include <iostream>
#include <algorithm>
using namespace std;
bool IsOdd (int i) { return ((i%2)==1); }
int main () {
int myints[] = {1,2,3,4,5,6,7,8,9};            // 1 2 3 4 5 6 7 8 9
// bounds of range:
int* pbegin = myints;                          // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^                 ^
pend = remove_if (pbegin, pend, IsOdd);        // 2 4 6 8 5 6 7 8 9
// ^       ^
cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
cout << " " << *p;
cout << endl;

return 0;
}
/*
Output:
range contains: 2 4 6 8
*/


7. 统计范围内等于指定值的元素个数 count()

http://www.cplusplus.com/reference/algorithm/count/

// count algorithm example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
int mycount;
// counting elements in array:
int myints[] = {10,20,30,30,20,10,10,20};   // 8 elements
mycount = (int) count (myints, myints+8, 10);
cout << "10 appears " << mycount << " times./n";
// counting elements in container:
vector<int> myvector (myints, myints+8);
mycount = (int) count (myvector.begin(), myvector.end(), 20);
cout << "20 appears " << mycount  << " times./n";
return 0;
}
/*
Output:
10 appears 3 times.
20 appears 3 times.
*/


统计范围内满足条件的元素个数 count_if()

http://www.cplusplus.com/reference/algorithm/count_if/

// count_if example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool IsOdd (int i) { return ((i%2)==1); }
int main () {
int mycount;
vector<int> myvector;
for (int i=1; i<10; i++) myvector.push_back(i); // myvector: 1 2 3 4 5 6 7 8 9
mycount = (int) count_if (myvector.begin(), myvector.end(), IsOdd);
cout << "myvector contains " << mycount  << " odd values./n";
return 0;
}
/*
Output:
myvector contains 5 odd values.
*/


8. 查找范围内等于指定值的第一个元素的位置 find()

http://www.cplusplus.com/reference/algorithm/find/

// find example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
int myints[] = { 10, 20, 30 ,40 };
int * p;
// pointer to array element:
p = find(myints,myints+4,30);
++p;
cout << "The element following 30 is " << *p << endl;
vector<int> myvector (myints,myints+4);
vector<int>::iterator it;
// iterator to vector element:
it = find (myvector.begin(), myvector.end(), 30);
++it;
cout << "The element following 30 is " << *it << endl;
return 0;
}
/*
Output:
The element following 30 is 40
The element following 30 is 40
*/


应用函数来查找 find_if()

http://www.cplusplus.com/reference/algorithm/find_if/

/*
|| How to find things in an STL list MkII
*/
#include <string>
#include <list>
#include <algorithm>

class EventIsIn1997 {
public:
bool operator () (string& EventRecord) {
// year field is at position 12 for 4 characters in EventRecord
return EventRecord.substr(12,4)=="1997";
}
};

void main (void) {
list<string> Events;

// string positions 0123456789012345678901234567890123456789012345
Events.push_back("07 January  1995 Draft plan of house prepared");
Events.push_back("07 February 1996 Detailed plan of house prepared");
Events.push_back("10 January  1997 Client agrees to job");
Events.push_back("15 January  1997 Builder starts work on bedroom");
Events.push_back("30 April    1997 Builder finishes work");

list<string>::iterator EventIterator = find_if (Events.begin(), Events.end(), EventIsIn1997());

// find_if completes the first time EventIsIn1997()() returns true
// for any object. It returns an iterator to that object which we
// can dereference to get the object, or if EventIsIn1997()() never
// returned true, find_if returns end()
if (EventIterator==Events.end()) {
cout << "Event not found in list" << endl;
}
else {
cout << *EventIterator << endl;
}
}
/*
这是程序的输出:
10 January 1997 Client agrees to job
*/


9. 查找序列 search()

http://www.cplusplus.com/reference/algorithm/search/

Searches the range [first1,last1) for the first occurrence of the sequence defined by [first2,last2), and returns an iterator to its first element.

// search algorithm example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool mypredicate (int i, int j) {
return (i==j);
}
int main () {
vector<int> myvector;
vector<int>::iterator it;
// set some values:        myvector: 10 20 30 40 50 60 70 80 90
for (int i=1; i<10; i++) myvector.push_back(i*10);
// using default comparison:
int match1[] = {40,50,60,70};
it = search (myvector.begin(), myvector.end(), match1, match1+4);
if (it!=myvector.end())
cout << "match1 found at position " << int(it-myvector.begin()) << endl;
else
cout << "match1 not found" << endl;
// using predicate comparison:
int match2[] = {20,30,50};
it = search (myvector.begin(), myvector.end(), match2, match2+3, mypredicate);
if (it!=myvector.end())
cout << "match2 found at position " << int(it-myvector.begin()) << endl;
else
cout << "match2 not found" << endl;

return 0;
}
/*
Output:
match1 found at position 3
match2 not found
*/


10 排序 sort()

11 Function Objects
http://www.cplusplus.com/reference/std/functional/
不以独立的函数加以定义而采用function objects是出于效率的考虑。可以令call运算符成为inline,消除了“通过函数指针来调用函数”的额外开销。

functional objects分为:

1、算术运算(arithmetic)

plus

Addition function object class (class template)

minus

Subtraction function object class (class template)

multiplies

Multiplication function object class (class template)

divides

Division function object class (class template)

modulus

Modulus function object class (class template)

negate

Negative function object class (class template)

2、关系(relational)

equal_to

Function object class for equality comparison (class template)

not_equal_to

Function object class for non-equality comparison (class template)

greater

Function object class for greater-than inequality comparison (class template)

less

Function object class for less-than inequality comparison (class template)

greater_equal

Function object class for greater-than-or-equal-to comparison (class template)

less_equal

Function object class for less-than-or-equal-to comparison (class template)

3、逻辑运算(logical)

logical_and

Logical AND function object class (class template)

logical_or

Logical OR function object class (class template)

logical_not

Logical NOT function object class (class template)

// greater example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
int numbers[]={20,40,50,10,30};
sort (numbers, numbers+5, greater<int>() );
for (int i=0; i<5; i++)
cout << numbers[i] << " ";
cout << endl;
return 0;
}


binder adapter (绑定配接器)

将function object的参数绑定至某个特定值身上,是binary(二元)function object转化为unary(一元)function object。

bind1st将指定值绑定至第一操作数,bind2nd将指定值绑定至第二操作数。

// bind2nd example
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main () {
int numbers[] = {10,-20,-30,40,-50};
int cx;
cx = count_if ( numbers, numbers+5, bind2nd(less<int>(),0) );
cout << "There are " << cx << " negative elements./n";
return 0;
}


back_inserter() 以容器的push_back()函数取代assignment运算符;

inserter() 以容器的inseter() 函数取代assignment运算符;

front_inserter() 以容器的push_front()函数取代assingment运算符。

mem_fun

将成员函数转为函数对象

例:和transform结合利用string::length获得string数组每个成员长度
http://www.cplusplus.com/reference/std/functional/mem_fun/
// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main () {
vector <string*> numbers;
// populate vector of pointers:
numbers.push_back ( new string ("one") );
numbers.push_back ( new string ("two") );
numbers.push_back ( new string ("three") );
numbers.push_back ( new string ("four") );
numbers.push_back ( new string ("five") );
vector <int> lengths ( numbers.size() );
transform (numbers.begin(), numbers.end(), lengths.begin(), mem_fun(&string::length));

for (int i=0; i<5; i++) {
cout << *numbers[i] << " has " << lengths[i] << " letters./n";
}
return 0;
}
/*
Output:
one has 3 letters.
two has 3 letters.
three has 5 letters.
four has 4 letters.
five has 4 letters
/*


ptr_fun

函数指针转函数对象

例:和accumulate结合利用atoi,累加保存为char字符串的数组
http://www.cplusplus.com/reference/std/functional/ptr_fun/
// ptr_fun example
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <numeric>
using namespace std;
int main () {
char* foo[] = {"10","20","30","40","50"};
int bar[5];
int sum;
transform (foo, foo+5, bar, ptr_fun(atoi) );
sum = accumulate (bar, bar+5, 0);
cout << "sum = " << sum << endl;
return 0;
}
/*
Possible output:
sum = 150
*/


Hash Set

http://www.moosechips.com/2008/10/using-gcc-c-hash-classes-with-strings/

// Example code using a hash_set with std::string keys on gcc
// Example based on hash_set code from "6.7 Using Hashed Containers"
// in O'Reilly C++ Cookbook by Stephens, Diggins, Turkanis & Cogswell  (2006)
// and gcc fix from post http://gcc.gnu.org/ml/libstdc++/2002-04/msg00107.html // Tested with g++ 4.1.2
// Compile with:
// g++ -o hash hash.cpp
// Kristi Tsukida <kristi.tsukida at gmail dot com> 30-10-2008

#include <iostream>
#include <string>
#include <ext/hash_set>

using namespace std;
// The __gnu_cxx namespace contains the hash_set since it's not standard c++
using namespace __gnu_cxx;

// This is the magic that will allow the usage of string keys in the hash
namespace __gnu_cxx
{
template<> struct hash< std::string >
{
size_t operator()( const std::string& x ) const
{
return hash< const char* >()( x.c_str() );
}
};
}

// must specify the hash<string> hash function
typedef hash_set<string, hash<string> > string_hash_set;

int main()
{
string_hash_set hs;

string s = "bravo";
hs.insert(s);
s = "alpha";
hs.insert(s);
s = "charlie";
hs.insert(s);

for(string_hash_set::const_iterator p = hs.begin(); p!= hs.end(); ++p)
{
cout << *p << endl;
}

}


Reference:



list来操作stl中的算法---其他的都相似!

详细解说 STL 排序(Sort)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: