标准化
年份 C++标准 俗称
2011 ISO/IEC 14882:2011[2] C++11 也被称为C++0x
2007 ISO/IEC TR 19768:2007[3] C++TR1
2003 ISO/IEC 14882:2003[4] C++03
1998 ISO/IEC 14882:1998[5] C++98
//=============================
c++11新特性
//-----------------------------
auto 关键字
自动帮助推导类型
auto i = 5 // i will be of type int
int n=3;
double pi=3.14;
auto j=pi*n; // j will be of type double
类型更难写的例子
// take a hypothetical Map of ( int and an map(int,int) )
map< int, map<int,int> > _Map;
// see the verbose for defining a const iterator of this map
map<int, map<int,int>>::const_iterator itr1 = _Map.begin();
// now with auto our life gets simplified
const auto itr2 = _Map.begin();
类型更难知晓的例子
template<class U, class V>
void Somefunction(U u, V v)
{
??? result = u*v; // now what would be the type of result ???
// with auto we leave the compiler to determine the type
auto result = u*v;
}
新特性要点总结
①我们可以使用valatile,pointer(*),reference(&),rvalue reference(&&) 来修饰auto
auto k = 5;
auto* pK = new auto(k);
auto** ppK = new auto(&k);
const auto n = 6;
②用auto声明的变量必须初始化
auto m; // m should be intialized
③auto不能与其他类型组合连用
auto int p; // no way
④函数和模板参数不能被声明为auto
void MyFunction(auto parameter){} // no auto as method argument
template<auto T> // utter nonsense - not allowed
void Fun(T t){}
⑤定义在堆上的变量,使用了auto的表达式必须被初始化
int* p = new auto(0); //fine
int* pp = new auto(); // should be initialized
auto x = new auto(); // Hmmm ... no intializer
auto* y = new auto(9); // Fine. Here y is a int*
auto z = new auto(9); //Fine. Here z is a int* (It is not just an int)
⑥以为auto是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其他一些操作,如sizeof和typeid
int value = 123;
auto x2 = (auto)value; // no casting using auto
auto x3 = static_cast<auto>(value); // same as above
⑦定义在一个auto序列的变量必须始终推导成同一类型
auto x1 = 5, x2 = 5.0, x3='r'; // This is too much....we cannot combine like this
⑧auto不能自动推导成CV-qualifiers(constant & volatile qualifiers),除非被声明为引用类型
const int i = 99;
auto j = i; // j is int, rather than const int
j = 100 // Fine. As j is not constant
// Now let us try to have reference
auto& k = i; // Now k is const int&
k = 100; // Error. k is constant
// Similarly with volatile qualifer
⑨auto会退化成指向数组的指针,除非被声明为引用
int a[9];
auto j = a;
cout<<typeid(j).name()<<endl; // This will print int*
auto& k = a;
cout<<typeid(k).name()<<endl; // This will print int [9]
//-----------------------------
decltype
返回值 decltype(表达式)
[返回值的类型是表达式参数的类型]
这个可也用来决定表达式的类型,就像Bjarne暗示的一样,如果我们需要去初始化某种类型的变量,auto是最简单的选择,但是如果我们所需的类型不是一个变量,例如返回值这时我们可也试一下decltype。
现在我们回看一些例子我们先前做过的,
[cpp] view plaincopy
template <class U, class V>
void Somefunction(U u, V v)
{
result = u*v;//now what type would be the result???
decltype(u*v) result = u*v;//Hmm .... we got what we want
}
在下面的一个段落我将会让你熟悉这个观念用 auto 和 decltype 来声明模板函数的返回值,其类型依靠模板参数。
1. 如果这个表达式是个函数,decltype 给出的类型为函数返回值的类型。
[cpp] view plaincopy
int add(int i, int j){ return i+j; }
decltype(add(5,6)) var = 5;//Here the type of var is return of add() -> which is int
2.如果表达式是一个左值类型,那么 decltype 给出的类型为表达式左值引用类型。
[cpp] view plaincopy
struct M { double x; };
double pi = 3.14;
const M* m = new M();
decltype( (m->x) ) piRef = pi;
// Note: Due to the inner bracets the inner statement is evaluated as expression,
// rather than member 'x' and as type of x is double and as this is lvale
// the return of declspec is double& and as 'm' is a const pointer
// the return is actually const double&.
// So the type of piRef is const double&
3.非常重要的标记一下,decltype 不会执行表达式而auto会,他仅仅推论一下表达式的类型。
[cpp] view plaincopy
int foo(){}
decltype( foo() ) x; // x is an int and note that
// foo() is not actually called at runtime
跟踪返回类型:
这对 C++ 开发者来说是一个全新的特性,直到现在函数的返回类型必须放在函数名的前面。到了 C++11,我们也可以将函数返回值的类型放在函数声明后,当然仅需要用 auto 替代返回类型。现在我们想知道怎么做,让我们来寻找答案:
[cpp] view plaincopy
template<class U, class V>
??? Multiply(U u, V v) // how to specifiy the type of the return value
{
return u*v;
}
我们明显的不能像这样:
[cpp] view plaincopy
template<class U, class V>
decltype(u*v) Multiply(U u, V v) // Because u & v are not defined before Multiply.
// What to do...what to do !!!
{
return u*v;
}
这种情况我们可也使用 auto 然后当我们使用 decltype(u*v) 作为返回值这个类型便知晓了.
这是不是很酷?
[cpp] view plaincopy
template<class U, class V>
auto Multiply(U u, V v) -> decltype(u*v) // Note -> after the function bracet.
{
return u*v;
}
//============================
STL算法:
STL中算法大致分为四类:
1、非可变序列算法:指不直接修改其所操作的容器内容的算法。
该算法不对所作用的容器进行修改,包括:
adjacent_find(),find(),find_end(),find_first(),count(),mismatch(),equal(),for_each()和search()等
2、可变序列算法:指可以修改它们所操作的容器内容的算法。
算法对所作用的容器进行修改,包括
copy(),copy_backward() fill() generate() partition() random_shuffle() remove() replace() rotate() reverse() swap() swap_ranges() transfrom() unique()
3、排序算法:包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
对容器的内容进行不同方式的排序,包括
sort() stable_sort() partial_sort() partial_sort_copy() nth_element() binary_search() lower_bound() upper_bound() equal_range() merger() includes() push_heap() pop_heap() make_heap() sort_heap() sort_heap() set_union() set_intersection set_difference()
set_symmertric_difference() min() min_element() max() max_element() lexicographical_compare() next_premutation() prev_permutation()
4、数值算法:对容器内容进行数值计算。
对容器的内容进行数值计算,包括
accumulate() innerproduct() partail_sum() adjacent_difference()
//---------------------
非修改性序列操作(12个)
循环
for_each()
对序列中的每个元素执行某操作
查找
find()
在序列中找出某个值的第一次出现的位置
find_if()
在序列中找出符合某谓词的第一个元素
find_end()
在序列中找出一子序列的最后一次出现的位置
find_first_of()
在序列中找出第一次出现指定值集中之值的位置
adjacent_find()
在序列中找出相邻的一对值
计数
count()
在序列中统计某个值出现的次数
count_if()
在序列中统计与某谓词匹配的次数
比较
mismatch()
找出两个序列相异的第一个元素
equal()
两个序列中的对应元素都相同时为真
搜索
search()
在序列中找出一子序列的第一次出现的位置
search_n()
在序列中找出一值的连续n次出现的位置
//---------------------
修改性序列操作(27个)
复制
copy()
从序列的第一个元素起进行复制
copy_backward()
从序列的最后一个元素起进行复制
交换
swap()
交换两个元素
swap_ranges()
交换指定范围的元素
iter_swap()
交换由迭代器所指的两个元素
变换
transform()
将某操作应用于指定范围的每个元素
替换
replace()
用一个给定值替换一些值
replace_if()
替换满足谓词的一些元素
replace_copy()
复制序列时用一给定值替换元素
replace_copy_if()
复制序列时替换满足谓词的元素
填充
fill()
用一给定值取代所有元素
fill_n()
用一给定值取代前n个元素
生成
generate()
用一操作的结果取代所有元素
generate_n()
用一操作的结果取代前n个元素
删除
remove()
删除具有给定值的元素
remove_if()
删除满足谓词的元素
remove_copy()
复制序列时删除具有给定值的元素
remove_copy_if()
复制序列时删除满足谓词的元素
唯一
unique()
删除相邻的重复元素
unique_copy()
复制序列时删除相邻的重复元素
反转
reverse()
反转元素的次序
reverse_copy()
复制序列时反转元素的次序
环移
rotate()
循环移动元素
rotate_copy()
复制序列时循环移动元素
随机
random_shuffle()
采用均匀分布来随机移动元素
划分
partition()
将满足某谓词的元素都放到前面
stable_partition()
将满足某谓词的元素都放到前面并维持原顺序
//---------------------
序列排序及相关操作(27个)
排序
sort()
以很好的平均效率排序
stable_sort()
排序,并维持相同元素的原有顺序
partial_sort()
将序列的前一部分排好序
partial_sort_copy()
复制的同时将序列的前一部分排好序
第n个元素
nth_element()
将第n各元素放到它的正确位置
二分检索
lower_bound()
找到大于等于某值的第一次出现
upper_bound()
找到大于某值的第一次出现
equal_range()
找到(在不破坏顺序的前提下)可插入给定值的最大范围
binary_search()
在有序序列中确定给定元素是否存在
归并
merge()
归并两个有序序列
inplace_merge()
归并两个接续的有序序列
有序结构上的集合操作
includes()
一序列为另一序列的子序列时为真
set_union()
构造两个集合的有序并集
set_intersection()
构造两个集合的有序交集
set_difference()
构造两个集合的有序差集
set_symmetric_difference()
构造两个集合的有序对称差集(并-交)
堆操作
push_heap()
向堆中加入元素
pop_heap()
从堆中弹出元素
make_heap()
从序列构造堆
sort_heap()
给堆排序
最大和最小
min()
两个值中较小的
max()
两个值中较大的
min_element()
序列中的最小元素
max_element()
序列中的最大元素
词典比较
lexicographical_compare()
两个序列按字典序的第一个在前
排列生成器
next_permutation()
按字典序的下一个排列
prev_permutation()
按字典序的前一个排列
//--------------------------------------------实例
STL算法.cpp : 定义控制台应用程序的入口点。
/*******************************************************************************
STL通用算法: Description:
1、非修正序列算法 不对其所作用的容器进行修改
2、修正序列算法 对其所作用的容器进行修改
3、排序算法 对容器的内容进行不同方式的排序
4、数值算法 对容器的内容进行数值计算
*******************************************************************************/
#include "stdafx.h"
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>
using namespace std;
////////////////////////////////////////////////////////////////////////////////////////////////////////////
第一类通用算法---非修正序列算法
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: adjacent_find(first,last)
Description: 搜索重复对
Parameter: 搜索时的起始位置
Return: 返回在该区间第一个重复的对.
By: capter
Date: 2005-12-23
*******************************************************/
int _tmain(int argc, _TCHAR* argv[])
{
multiset<int> intset;
intset.insert(10);
intset.insert(3);
intset.insert(1);
intset.insert(3);
intset.insert(8);
intset.insert(8);
intset.insert(5);
//显示该多重集合
multiset<int>::iterator iter;
for(iter=intset.begin(); iter!=intset.end(); iter++)
cout<<*iter<<" ";
cout<<endl;
//查找第一个相等的值
iter = adjacent_find(intset.begin(),intset.end());
cout<<*iter<<endl;
iter++;
cout<<*iter<<endl;
return 0;
}
/*******************************************************
Function: count(first,last,val)
Description: 计算val出现的次数
Parameter: 搜索时的起始位置和要计算的值
Return: 返回出现的次数
By: capter
Date: 2005-12-23
*******************************************************/
int main()
{
multiset<int> intset;
intset.insert(10);
intset.insert(6);
intset.insert(1);
intset.insert(3);
intset.insert(6);
intset.insert(2);
intset.insert(3);
//显示该多重集合的值
multiset<int>::iterator iter;
for(iter=intset.begin(); iter!=intset.end(); iter++)
cout<<*iter<<" ";
cout<<endl;
//搜索数字3出现的次数
int n = count(intset.begin(),intset.end(),3);
cout<<"数字3在该多重集合中共出现了:"<<n<<"次"<<endl;
return 0;
}
/*******************************************************
Function: for_each(first,last,func)
Description: 对first,last范围内每个元素执行func定义的函数
Parameter: first,last要执行元素的范围,func自己定义的函数
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
int main()
{
multiset<int> intset;
intset.insert(10);
intset.insert(6);
intset.insert(1);
intset.insert(3);
intset.insert(6);
intset.insert(2);
intset.insert(3);
//显示该多重集合的值
for_each(intset.begin(),intset.end(),showvalue);
cout<<endl;
return 0;
}
//////////////////////////////////////////////////
第一类--非修正序列算法还有其他函数
equal(first,last,first2)
find(first,last,val)
find_end(first,last,first2,last2)
find_first(first,last,first2,last2)
mismatch(first,last,first2)
search(first,last,first2,last2)
//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
第二类通用算法---修正序列算法
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: fill(first,last,val)
Description: 把val的值赋给first,last中所有的元素
Parameter: 起始位置和要赋的值
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> intvector;
for(int x=0;x<10;x++)
intvector.push_back(x);
//显示该向量的内容
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
//填充该值
fill(intvector.begin(),intvector.begin()+5,0);
//显示填充后的值
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
return 0;
}
/*******************************************************
Function: random_shuffle(first,last)
Description: 在指示器first,last中随机排列元素
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> intvector;
for(int x=0;x<10;x++)
intvector.push_back(x);
//显示该向量的值
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
//对该向量进行随机排序
random_shuffle(intvector.begin(),intvector.end());
//显示随机排序后的值
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
return 0;
}
/*******************************************************
Function: partition(first,last,pred)
Description: 在指示器first,last中经过谓词的判断后一分为二
Parameter: 起始位置和谓词
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
//谓词函数
bool equals5(int val)
{
return (val == 5);
}
int main()
{
vector<int> intvector;
intvector.push_back(8);
intvector.push_back(5);
intvector.push_back(7);
intvector.push_back(5);
intvector.push_back(2);
intvector.push_back(5);
//显示该向量的内容
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
//对该向量进行分段
partition(intvector.begin(),intvector.end(),equals5);
//显示新内容
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
return 0;
}
/*******************************************************
Function: rotate(first,middle,last)
Description: 把从middle到last的元素旋转到first范围处
Parameter: 起始位置和开始旋转位置
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(char x)
{
cout<<x<<" ";
}
int main()
{
vector<char> charvector;
for(int i=0;i<10;i++)
charvector.push_back(65+i);
//显示向量内容
for_each(charvector.begin(),charvector.end(),showvalue);
cout<<endl;
//旋转
rotate(charvector.begin(),charvector.begin()+6,charvector.end());
//显示旋转后的内容
for_each(charvector.begin(),charvector.end(),showvalue);
cout<<endl;
return 0;
}
//////////////////////////////////////////////////
copy(first,last,first2)
copy_backward(first,last,first2)
generate(first,last,func)
remove(first,last,val)
replace(first,last,val1,val2)
reverse(first,last)
swap(it1,it2)
swap_ranges(first,last,first2)
transform(first,last,first2,func)
unique(first,last)
//////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
第三类通用算法---排序算法
/////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: sort(first,last)
Description: 排序
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void show(char val)
{
cout<<val<<" ";
}
int main()
{
vector<char> charvector;
charvector.push_back('Z');
charvector.push_back('D');
charvector.push_back('F');
charvector.push_back('S');
charvector.push_back('A');
charvector.push_back('Q');
charvector.push_back('C');
charvector.push_back('G');
charvector.push_back('M');
charvector.push_back('Y');
//显示向量
for_each(charvector.begin(),charvector.end(),show);
cout<<endl;
//排序
sort(charvector.begin(),charvector.end());
//显示排序后的向量
for_each(charvector.begin(),charvector.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: partial_sort(first,middle,last)
Description: 进行偏序排序
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void show(string val)
{
cout<<val<<endl;
}
int main()
{
vector<string> strvector;
strvector.push_back("zebra");
strvector.push_back("deer");
strvector.push_back("fish");
strvector.push_back("snake");
strvector.push_back("bat");
strvector.push_back("cat");
strvector.push_back("bird");
strvector.push_back("turtle");
strvector.push_back("horse");
strvector.push_back("cow");
//显示向量内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
//进行偏序排序
partial_sort(strvector.begin(),strvector.begin()+5,strvector.end());
//显示排序后的内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: nth_element(first,nth,last)
Description: 排序
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void show(string val)
{
cout<<val<<endl;
}
int main()
{
vector<string> strvector;
strvector.push_back("zebra");
strvector.push_back("deer");
strvector.push_back("fish");
strvector.push_back("snake");
strvector.push_back("bat");
strvector.push_back("cat");
strvector.push_back("bird");
strvector.push_back("turtle");
strvector.push_back("horse");
strvector.push_back("cow");
//显示向量内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
//进行偏序排序
nth_element(strvector.begin(),strvector.begin()+5,strvector.end());
//显示排序后的内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: merge(first,last,first2,last2,result)
Description: 合并排序
Parameter: 起始位置和结果集
By: capter
Date: 2005-12-23
*******************************************************/
void show(string val)
{
cout<<val<<endl;
}
int main()
{
vector<string> strvector1,strvector2;
vector<string> strvector3(10);
strvector1.push_back("zebra");
strvector1.push_back("deer");
strvector1.push_back("fish");
strvector1.push_back("snake");
strvector1.push_back("bat");
strvector2.push_back("cat");
strvector2.push_back("bird");
strvector2.push_back("turtle");
strvector2.push_back("horse");
strvector2.push_back("cow");
//显示向量内容
for_each(strvector1.begin(),strvector1.end(),show);
cout<<endl;
//显示排序后的内容
for_each(strvector2.begin(),strvector2.end(),show);
cout<<endl;
sort(strvector1.begin(),strvector1.end());
sort(strvector2.begin(),strvector2.end());
merge(strvector1.begin(),strvector1.end(),strvector2.begin(),strvector2.end(),strvector3.begin());
//显示排序后的结果
for_each(strvector3.begin(),strvector3.end(),show);
cout<<endl;
return 0;
}
/////////////////////////////////////////////////////////////////////
第二种通用算法还有以下几种
binary_search(first,last,val)
equal_range(first,last,val)
includes(first,last,first2,last2)
lexicographical_compare(first,last,first2,last2)
lower_bound(first,last,val)
make_heap(first,last)
max(val1,val2)
max_element(first,last)
min(val1,val2)
next_permutation(first,last)
partial_sort_copy(first,last,first2,last2);
pop_heap(first,last)
prev_permutation(first,last)
push_heap(first,last)
set_difference(first,last,first2,last2,result)
set_intersection(first,last,first2,last2,result)
set_symmetric_difference(first,last,first2,last2,result)
set_union(first,last,first2,last2,result)
sort(first,last)
sort_heap(first,last)
stable_sort(first,last)
upper_bound(first,last,val)
////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第四种算法---数值算法
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: accumulate(first,last,init)
Description: 求和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> intvector;
for(int x=0; x<5; ++x)
intvector.push_back(x);
//显示内容
for_each(intvector.begin(),intvector.end(),show);
//求和
int result = accumulate(intvector.begin(),intvector.end(),5);
cout<<result<<endl;
return 0;
}
/*******************************************************
Function: inner_product(first,last,first2,init)
Description: 两向量对应的值相加,然后再求和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> vector1,vector2;
for(int i=0;i<5;i++)
vector1.push_back(i);
for(int i=2;i<7;i++)
vector2.push_back(i);
for_each(vector1.begin(),vector1.end(),show);
cout<<endl;
for_each(vector2.begin(),vector2.end(),show);
cout<<endl;
int result = inner_product(vector1.begin(),vector1.end(),vector2.begin(),0);
cout<<result<<endl;
return 0;
}
/*******************************************************
Function: partial_sum(first,last,first2,init)
Description: 求部分和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> vector1;
vector<int> vector2(5);
for(int i=2;i<7;++i)
vector1.push_back(i);
//显示向量内容
for_each(vector1.begin(),vector1.end(),show);
cout<<endl;
//求部分和
partial_sum(vector1.begin(),vector1.end(),vector2.begin());
//显示求和后的结果
for_each(vector2.begin(),vector2.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: adjacent_difference(first,last,first2,result)
Description: 两向量对应的值相加,然后再求和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> vector1;
vector<int> vector2(5);
vector1.push_back(3);
vector1.push_back(4);
vector1.push_back(12);
vector1.push_back(6);
vector1.push_back(10);
显示向量内容
for_each(vector1.begin(),vector1.end(),show);
cout<<endl;
求部分差
adjacent_difference(vector1.begin(),vector1.end(),vector2.begin());
显示求和后的结果
for_each(vector2.begin(),vector2.end(),show);
cout<<endl;
return 0;
}
C++STL 常用算法,使用时包含#include <algorithm>
一、非变异算法
是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理、元素查找、子序列搜索、统计和匹配。非变异算法具有极为广泛的适用性,基本上可应用与各种容器。
1查找容器元素find
它用于查找等于某值的元素。它在迭代器区间[first,last)(闭开区间)上查找等于value值的元素,如果迭代器i所指的元素满足*i=value,则返回迭代器i;未找到满足条件的元素,返回last。函数原型:find( v1.begin(), v1.end(), num_to_find );
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
int num_to_find = 6;
vector<int> v1;
for( int i = 0; i < 10; i++ )
v1.push_back(2*i);
vector<int>::iterator result;
result = find( v1.begin(), v1.end(), num_to_find );
if( result == v1.end() )
cout << "未找到任何元素匹配 " << num_to_find << endl;
else
cout << "匹配元素的索引值是 " << result-v1.begin() << endl;
}
2条件查找容器元素find_if
利用返回布尔值的谓词判断pred,检查迭代器区间[first,last)(闭开区间)上的每一个元素,如果迭代器i满足pred(*i)=true,表示找到元素并返回迭代值i(找到的第一个符合条件的元素);未找到元素,返回末位置last。函数原型:find_if(v.begin(),v.end(),divby5);
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool divby5(int x)
{
return x%5?0:1;
}
void main()
{
vector<int> v(20);
for(int i=0;i<v.size();i++)
{
v[i]=(i+1)*(i+3);
cout<<v[i]<<' ';
}
cout<<endl;
vector<int>::iterator ilocation;
ilocation=find_if(v.begin(),v.end(),divby5);
if(ilocation!=v.end())
cout<<"找到第一个能被5整除的元素:"<<*ilocation<<endl<<"元素的索引位置是: "<<ilocation-v.begin()<<endl;
}
3统计等于某值的容器元素个数count
list<int> l;
count(l.begin(),l.end(),value)
4条件统计count_if
count_if(l.begin(),l.end(),pred)。谓词pred含义同find_if中的谓词。例子可以参考例2.
5子序列搜索search
search算法函数在一个序列中搜索与另一序列匹配的子序列。参数分别为一个序列的开始位置,结束位置和另一个序列的开始,结束位置。
函数原型:search(v1.begin(),v1.end(),v2.begin(),v2.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v1;
cout<<"v1:";
for(int i=0;i<5;i++)
{
v1.push_back(i+5);
//注意:v1定义时没有给定大小,因此这里不能直接使用赋值语句。
cout<<v1[i]<<' ';
}
cout<<endl;
vector<int> v2;
cout<<"v2:";
for(i=0;i<2;i++)
{
v2.push_back(i+7);
cout<<v2[i]<<' ';
}
cout<<endl;
vector<int>::iterator ilocation;
ilocation=search(v1.begin(),v1.end(),v2.begin(),v2.end());
if(ilocation!=v1.end())
cout<<"v2的元素包含在v1中,起始元素为"<<"v1["<<ilocation-v1.begin()<<']'<<endl;
else
cout<<"v2的元素不包含在v1中"<<endl;
}
6重复元素子序列搜索search_n
search_n算法函数搜索序列中是否有一系列元素值均为某个给定值的子序列。函数原型:search_n(v.begin(),v.end(),3,8),在v中找到3个连续的元素8
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(1);
v.push_back(8);
v.push_back(8);
v.push_back(8);
v.push_back(6);
v.push_back(6);
v.push_back(8);
vector<int>::iterator i;
i=search_n(v.begin(),v.end(),3,8);
if(i!=v.end())
cout<<"在v中找到3个连续的元素8"<<endl;
else
cout<<"在v中未找到3个连续的元素8"<<endl;
}
7最后一个子序列搜索find_end
函数原型find_end(v1.begin(),v1.end(),v2.begin(),v2.end());在V1中要求的位置查找V2中要求的序列。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v1;
v1.push_back(-5);
v1.push_back(1);
v1.push_back(2);
v1.push_back(-6);
v1.push_back(-8);
v1.push_back(1);
v1.push_back(2);
v1.push_back(-11);
vector<int> v2;
v2.push_back(1);
v2.push_back(2);
vector<int>::iterator i;
i=find_end(v1.begin(),v1.end(),v2.begin(),v2.end());
if(i!=v1.end())
cout<<"v1中找到最后一个匹配v2的子序列,位置在" <<"v1["<<i-v1.begin()<<"]"<<endl;
}
二、变异算法
是一组能够修改容器元素数据的模板函数。copy(v.begin(),v.end(),l.begin());将v中的元素复制到l中。
1元素复制copy
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(5);
list<int> l;
l.push_back(2);
l.push_back(4);
l.push_back(6);
l.push_back(8);
l.push_back(10);
copy(v.begin(),v.end(),l.begin());
list<int>::iterator i;
for(i=l.begin();i!=l.end();i++)
cout<<*i<<' ';
cout<<endl;
}
2元素变换transform改变
函数原型:transform(v.begin(),v.end(),l.begin(),square);也是复制,但是要按某种方案复制。
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;
int square(int x)
{
return x*x;
}
void main()
{
vector<int> v;
v.push_back(5);
v.push_back(15);
v.push_back(25);
list<int> l(3);
transform(v.begin(),v.end(),l.begin(),square);
list<int>::iterator i;
for(i=l.begin();i!=l.end();i++)
cout<<*i<<' ';
cout<<endl;
}
3替换replace
replace算法将指定元素值替换为新值。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(13);
v.push_back(25);
v.push_back(27);
v.push_back(25);
v.push_back(29);
replace(v.begin(),v.end(),25,100);
vector<int>::iterator i;
for(i=v.begin();i!=v.end();i++)
cout<<*i<<' ';
cout<<endl;
}
输出结果为13 100 27 100 29
4条件替换replace_if
函数原型:replace_if(v.begin(),v.end(),odd,100);
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool odd(int x)
{
return x%2;
}
void main()
{
vector<int> v;
for(int i=1;i<10;i++)
v.push_back(i);
replace_if(v.begin(),v.end(),odd,100);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
5n次填充fill_n
函数原型fill_n(v.begin(),5,-1);向从v.begin开始的后面5个位置跳入-1
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v(10);
fill_n(v.begin(),5,-1);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
输出结果:-1 -1 -1 -1 -1 0 0 0 0 0
6随机生成n个元素generate
函数原型:generate_n(v.begin(),5,rand);向从v.begin开始的后面5个位置随机填写数据。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v(10);
generate_n(v.begin(),5,rand);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
7条件移除remove_if
返回值相当于移除满足条件的元素后形成的新向量的end()值。
函数原型:remove_if(v.begin(),v.end(),even);
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool even(int x)
{
return x%2?0:1;
}
void main()
{
vector<int> v;
for(int i=1;i<=10;i++)
v.push_back(i);
vector<int>::iterator ilocation,result;
cout<<"移除前:";
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
result=remove_if(v.begin(),v.end(),even);
cout<<"移除后:";
for(ilocation=v.begin();ilocation!=result;ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
8剔除连续重复元素unique
函数原型:unique(v.begin(),v.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(2);
v.push_back(6);
v.push_back(6);
v.push_back(6);
v.push_back(9);
v.push_back(6);
v.push_back(3);
vector<int>::iterator ilocation,result;
result=unique(v.begin(),v.end());
for(ilocation=v.begin();ilocation!=result;ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
输出结果:2 6 9 6 3
三、排序算法
1、创建堆make_heap
2、元素入堆push_heap(默认插入最后一个元素)
3、元素出堆pop_heap(与push_heap一样,pop_heap必须对堆操作才有意义)
#include <vector>??????
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(5);
v.push_back(6);
v.push_back(4);
v.push_back(8);
v.push_back(2);
v.push_back(3);
v.push_back(7);
v.push_back(1);
v.push_back(9);
make_heap(v.begin(),v.end());
v.push_back(20);
push_heap(v.begin(),v.end());
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
pop_heap(v.begin(),v.end());
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
4堆排序sort_heap
使用:
make_heap(v.begin(),v.end());
sort_heap(v.begin(),v.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(3);
v.push_back(9);
v.push_back(6);
v.push_back(3);
v.push_back(17);
v.push_back(20);
v.push_back(12);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
make_heap(v.begin(),v.end());
sort_heap(v.begin(),v.end());
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
输出结果:
3 9 6 3 17 20 12
3 3 6 9 12 17 20
5排序sort
函数原型:sort(v.begin(),v.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(2);
v.push_back(8);
v.push_back(-15);
v.push_back(90);
v.push_back(26);
v.push_back(7);
v.push_back(23);
v.push_back(30);
v.push_back(-27);
v.push_back(39);
v.push_back(55);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
sort(v.begin(),v.end());//比较函数默认
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
//============================
STL容器
test.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <stack>
using namespace std;
//向量类模板
int main()
{
std::vector<char> charvector;
int x = 0;
for(int i=0; i<10;i++)
charvector.push_back(65 + i);
std::vector<char>::iterator iter;
for(iter=charvector.begin();iter!=charvector.end();iter++)
{
cout<<"Element #"<<x++<<" : "<<*iter<<endl;
}
cout<<"当前数组的个数为:"<<charvector.size()<<endl;
vector<char>::iterator start = charvector.begin();
charvector.insert(start,5,'x');
cout<<"after insert :"<<endl;
for(iter=charvector.begin();iter!=charvector.end();iter++)
cout<<*iter;
cout<<endl;
cout<<"after delete :"<<endl;
int size=charvector.size();
for(int i=0;i<size;i++)
{
vector<char>::iterator start = charvector.begin();
charvector.erase(start);
vector<char>::iterator iter1;
for(iter1=charvector.begin();iter1!=charvector.end();iter1++)
cout<<*iter1;
cout<<endl;
}
return 0;
}
//双端队列类模板
int main()
{
deque<char> chardeque;
for(int i=0;i<10;++i)
chardeque.push_front(65+i);
int size=chardeque.size();
deque<char>::iterator iter;
for(iter=chardeque.begin();iter!=chardeque.end();iter++)
cout<<*iter;
for(int i=0;i<size;i++)
{
chardeque.pop_back();
for(iter=chardeque.begin();iter!=chardeque.end();iter++)
cout<<*iter;
cout<<endl;
}
return 0;
}
//链表类模板
int main()
{
list<char> charlist;
int x=0;
for(int i=0;i<10;i++)
charlist.push_front(65+i);
list<char>::iterator iter;
for(iter=charlist.begin();iter!=charlist.end();iter++)
cout<<*iter;
cout<<endl;
list<char>::iterator start=charlist.begin();
charlist.insert(++start,5,'x');
for(iter=charlist.begin();iter!=charlist.end();iter++)
cout<<*iter;
cout<<endl;
return 0;
}
//容器适配器stack
int main()
{
stack<int,list<int> > intstack;
for(int x=1;x<=10;x++)
{
intstack.push(x*100);
}
int size=intstack.size();
for(int i=0;i<size;i++)
{
cout<<intstack.top()<<endl;
intstack.pop();
}
return 0;
}
//容器适配器queue
int main()
{
queue<int,list<int> > intqueue;
for(int x=1; x<=10; x++)
{
intqueue.push(x*100);
}
int size = intqueue.size();
for(int i=0;i<size;i++)
{
cout<<"intqueue "<<intqueue.front()<<endl;
intqueue.pop();
}
return 0;
}
//优先级队列
int main()
{
std::priority_queue<int, std::vector<int>,std::greater<int> > intp_queue;
intp_queue.push(400);
intp_queue.push(100);
intp_queue.push(500);
intp_queue.push(300);
intp_queue.push(200);
int size = intp_queue.size();
for(int i=0; i<size; i++)
{
cout<<" "<<intp_queue.top()<<endl;
intp_queue.pop();
}
cout<<endl;
return 0;
}
//集合
int main()
{
set<int> intset;//升序
intset.insert(10);
intset.insert(5);
intset.insert(1);
intset.insert(3);
intset.insert(8);
set<int>::iterator iter;
for(iter=intset.begin();iter!=intset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
cout<<"after delete :"<<endl;
set<int>::iterator start;
start=intset.begin();
intset.erase(start++);
for(iter=intset.begin();iter!=intset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
cout<<"find data in set"<<endl;
iter = intset.find(5);
if(iter == intset.end())
cout<<"can't find 5"<<endl;
else
cout<<"ok,find the 5"<<endl;
return 0;
}
//多重数据集
int main()
{
multiset<int> intmset;
intmset.insert(10);
intmset.insert(5);
intmset.insert(1);
intmset.insert(3);
intmset.insert(8);
intmset.insert(5);
intmset.insert(8);
multiset<int>::iterator iter;
for(iter=intmset.begin();iter!=intmset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
iter=intmset.begin();
intmset.erase(++iter);
for(iter=intmset.begin();iter!=intmset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
iter=intmset.find(3);
if(iter==intmset.end())
cout<<"sorry,it's error !"<<endl;
else
cout<<"It's find the 3"<<endl;
return 0;
}
//映射
int main()
{
map<int,char> charmap;
charmap.insert(map<int,char>::value_type(1,'A'));
charmap.insert(map<int,char>::value_type(5,'B'));
charmap.insert(map<int,char>::value_type(2,'C'));
charmap.insert(map<int,char>::value_type(3,'D'));
charmap.insert(map<int,char>::value_type(4,'E'));
map<int,char>::iterator iter;
for(iter=charmap.begin();iter!=charmap.end();iter++)
cout<<(*iter).first<<"--"<<(*iter).second<<" ";
cout<<endl;
cout<<"after delete :"<<endl;
iter = charmap.begin();
charmap.erase(++iter);
for(iter=charmap.begin();iter!=charmap.end();iter++)
cout<<(*iter).first<<"--"<<(*iter).second<<" ";
cout<<endl;
std::map<int ,char>::iterator i=charmap.find(4);
if(i==charmap.end())
cout<<"sorry,can't find"<<endl;
else
cout<<"ok,it's find"<<endl;
return 0;
}
//位集合
void display(std::bitset<8> bs)
{
cout<<"bitset = ";
for(int i=0;i<8;i++)
cout<<bs[i];
cout<<endl;
}
int main()
{
bitset<8> bitset;
display(bitset);
cout<<"set bits 1,2,3,5,7"<<endl;
bitset.set(1);
bitset.set(2);
bitset.set(3);
bitset.set(5);
bitset.set(7);
display(bitset);
cout<<"reset bits 2,3"<<endl;
bitset.reset(2);
bitset.reset(3);
display(bitset);
for(int i=0;i<8;i++)
{
cout<<"bit "<<i<<" is ";
if(bitset.test(i))//位的测试
cout<<"set"<<endl;
else
cout<<"unset"<<endl;
}
return 0;
}
//------------容器使用实例
只有顺序容器和关联容器支持迭代器遍历,各容器支持的迭代器的类别如下:
容器
支持的迭代器类别
说明
vector
随机访问
一种随机访问的数组类型,提供了对数组元素进行快速随机访问以及在序列尾部进行快速的插入和删除操作的功能。可以再需要的时候修改其自身的大小
deque
随机访问
一种随机访问的数组类型,提供了序列两端快速进行插入和删除操作的功能。可以再需要的时候修改其自身的大小
list
双向
一种不支持随机访问的数组类型,插入和删除所花费的时间是固定的,与位置无关。
set
双向
一种随机存取的容器,其关键字和数据元素是同一个值。所有元素都必须具有惟一值。
multiset
双向
一种随机存取的容器,其关键字和数据元素是同一个值。可以包含重复的元素。
map
双向
一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个特定的关键字只能与一个元素关联。
multimap
双向
一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个关键字可以与多个数据元素关联。
stack
不支持
适配器容器类型,用vector,deque或list对象创建了一个先进后出容器
queue
不支持
适配器容器类型,用deque或list对象创建了一个先进先出容器
priority_queue
不支持
适配器容器类型,用vector或deque对象创建了一个排序队列
下面列举了些例子说明各个容器的用法:
1、vector
#include <iostream>
#include <vector>
int main()
{
std::vector<char> charVector;
int x;
for (x=0; x<10; ++x)
charVector.push_back(65 + x);
int size = charVector.size();
for (x=0; x<size; ++x)
{
std::vector<char>::iterator start =
charVector.begin();
charVector.erase(start);
std::vector<char>::iterator iter;
for (iter = charVector.begin();
iter != charVector.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
}
return 0;
}
2、deque
#include <iostream>
#include <deque>
int main()
{
std::deque<char> charDeque;
int x;
for (x=0; x<10; ++x)
charDeque.push_front(65 + x);
int size = charDeque.size();
for (x=0; x<size; ++x)
{
std::deque<char>::iterator start =
charDeque.begin();
charDeque.erase(start);
std::deque<char>::iterator iter;
for (iter = charDeque.begin();
iter != charDeque.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
}
return 0;
}
3、list
#include <iostream>
#include <list>
int main()
{
// Create and populate the list.
int x;
std::list<char> charList;
for (x=0; x<10; ++x)
charList.push_front(65 + x);
// Display contents of list.
std::cout << "Original list: ";
std::list<char>::iterator iter;
for (iter = charList.begin();
iter != charList.end(); iter++)
{
std::cout << *iter;
//char ch = *iter;
//std::cout << ch;
}
std::cout << std::endl;
// Insert five Xs into the list.
std::list<char>::iterator start = charList.begin();
charList.insert(++start, 5, 'X');
// Display the result.
std::cout << "Resultant list: ";
for (iter = charList.begin();
iter != charList.end(); iter++)
{
std::cout << *iter;
//char ch = *iter;
//std::cout << ch;
}
return 0;
}
4、set
#include <iostream>
#include <set>
int main()
{
// Create the set object.
std::set<char> charSet;
// Populate the set with values.
charSet.insert('E');
charSet.insert('D');
charSet.insert('C');
charSet.insert('B');
charSet.insert('A');
// Display the contents of the set.
std::cout << "Contents of set: " << std::endl;
std::set<char>::iterator iter;
for (iter = charSet.begin(); iter != charSet.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Find the D.
iter = charSet.find('D');
if (iter == charSet.end())
std::cout << "Element not found.";
else
std::cout << "Element found: " << *iter;
return 0;
}
5、multiset
#include <iostream>
#include <set>
int main()
{
// Create the first set object.
std::multiset<char> charMultiset1;
// Populate the multiset with values.
charMultiset1.insert('E');
charMultiset1.insert('D');
charMultiset1.insert('C');
charMultiset1.insert('B');
charMultiset1.insert('A');
charMultiset1.insert('B');
charMultiset1.insert('D');
// Display the contents of the first multiset.
std::cout << "Contents of first multiset: " << std::endl;
std::multiset<char>::iterator iter;
for (iter = charMultiset1.begin();
iter != charMultiset1.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Create the second multiset object.
std::multiset<char> charMultiset2;
// Populate the multiset with values.
charMultiset2.insert('J');
charMultiset2.insert('I');
charMultiset2.insert('H');
charMultiset2.insert('G');
charMultiset2.insert('F');
charMultiset2.insert('G');
charMultiset2.insert('I');
// Display the contents of the second multiset.
std::cout << "Contents of second multiset: "
<< std::endl;
for (iter = charMultiset2.begin();
iter != charMultiset2.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Compare the sets.
if (charMultiset1 == charMultiset2)
std::cout << "set1 == set2";
else if (charMultiset1 < charMultiset2)
std::cout << "set1 < set2";
else if (charMultiset1 > charMultiset2)
std::cout << "set1 > set2";
return 0;
}
6、map
#include <iostream>
#include <map>
typedef std::map<int, char> MYMAP;
int main()
{
// Create the first map object.
MYMAP charMap1;
// Populate the first map with values.
charMap1[1] = 'A';
charMap1[4] = 'D';
charMap1[2] = 'B';
charMap1[5] = 'E';
charMap1[3] = 'C';
// Display the contents of the first map.
std::cout << "Contents of first map: " << std::endl;
MYMAP::iterator iter;
for (iter = charMap1.begin();
iter != charMap1.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Create the second map object.
MYMAP charMap2;
// Populate the first map with values.
charMap2[1] = 'F';
charMap2[4] = 'I';
charMap2[2] = 'G';
charMap2[5] = 'J';
charMap2[3] = 'H';
// Display the contents of the second map.
std::cout << "Contents of second map: " << std::endl;
for (iter = charMap2.begin();
iter != charMap2.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Compare the maps.
if (charMap1 == charMap2)
std::cout << "map1 == map2";
else if (charMap1 < charMap2)
std::cout << "map1 < map2";
else if (charMap1 > charMap2)
std::cout << "map1 > map2";
return 0;
}
7、multimap
#include <iostream>
#include <map>
typedef std::multimap<int, char> MYMAP;
int main()
{
// Create the first multimap object.
MYMAP charMultimap;
// Populate the multimap with values.
charMultimap.insert(MYMAP::value_type(1,'A'));
charMultimap.insert(MYMAP::value_type(4,'C'));
charMultimap.insert(MYMAP::value_type(2,'B'));
charMultimap.insert(MYMAP::value_type(7,'E'));
charMultimap.insert(MYMAP::value_type(5,'D'));
charMultimap.insert(MYMAP::value_type(3,'B'));
charMultimap.insert(MYMAP::value_type(6,'D'));
// Display the contents of the first multimap.
std::cout << "Contents of first multimap: " << std::endl;
MYMAP::iterator iter;
for (iter = charMultimap.begin();
iter != charMultimap.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Create the second multimap object.
MYMAP charMultimap2;
// Populate the second multimap with values.
charMultimap2.insert(MYMAP::value_type(1,'C'));
charMultimap2.insert(MYMAP::value_type(4,'F'));
charMultimap2.insert(MYMAP::value_type(2,'D'));
charMultimap2.insert(MYMAP::value_type(7,'E'));
charMultimap2.insert(MYMAP::value_type(5,'F'));
charMultimap2.insert(MYMAP::value_type(3,'E'));
charMultimap2.insert(MYMAP::value_type(6,'G'));
// Display the contents of the second multimap.
std::cout << "Contents of second multimap: " << std::endl;
for (iter = charMultimap2.begin();
iter != charMultimap2.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Compare the multimaps.
if (charMultimap == charMultimap2)
std::cout << "multimap1 == multimap2";
else if (charMultimap < charMultimap2)
std::cout << "multimap1 < multimap2";
else if (charMultimap > charMultimap2)
std::cout << "multimap1 > multimap2";
return 0;
}
8、stack
#include <iostream>
#include <list>
#include <stack>
int main()
{
std::stack<int, std::list<int> > intStack;
int x;
std::cout << "Values pushed onto stack:"
<< std::endl;
for (x=1; x<11; ++x)
{
intStack.push(x*100);
std::cout << x*100 << std::endl;
}
std::cout << "Values popped from stack:"
<< std::endl;
int size = intStack.size();
for (x=0; x<size; ++x)
{
std::cout << intStack.top() << std::endl;
intStack.pop();
}
return 0;
}
9、queue
#include <iostream>
#include <list>
#include <queue>
int main()
{
std::queue<int, std::list<int> > intQueue;
int x;
std::cout << "Values pushed onto queue:"
<< std::endl;
for (x=1; x<11; ++x)
{
intQueue.push(x*100);
std::cout << x*100 << std::endl;
}
std::cout << "Values removed from queue:"
<< std::endl;
int size = intQueue.size();
for (x=0; x<size; ++x)
{
std::cout << intQueue.front() << std::endl;
intQueue.pop();
}
return 0;
}
10、priority_queue
#include <iostream>
#include <list>
#include <queue>
int main()
{
std::priority_queue<int, std::vector<int>,std::greater<int> > intPQueue;
int x;
intPQueue.push(400);
intPQueue.push(100);
intPQueue.push(500);
intPQueue.push(300);
intPQueue.push(200);
std::cout << "Values removed from priority queue:"
<< std::endl;
int size = intPQueue.size();
for (x=0; x<size; ++x)
{
std::cout << intPQueue.top() << std::endl;
intPQueue.pop();
}
return 0;
}
//====================================================
STL 迭代器
标准模板库(The Standard Template Library, STL)定义了五种迭代器。下面的图表画出了这几种:
input output
\ /
forward
|
bidirectional
|
random access
要注意,上面这图表并不是表明它们之间的继承关系:而只是描述了迭代器的种类和接口。处于图表下层的迭代器都是相对于处于图表上层迭代器的扩张集。例如:forward迭代器不但拥有input和output迭代器的所有功能,还拥有更多的功能。
各个迭代器的功能如下:
迭代器类别
说明
输入
从容器中读取元素。输入迭代器只能一次读入一个元素向前移动,输入迭代器只支持一遍算法,同一个输入迭代器不能两遍遍历一个序列
输出
向容器中写入元素。输出迭代器只能一次一个元素向前移动。输出迭代器只支持一遍算法,统一输出迭代器不能两次遍历一个序列
正向
组合输入迭代器和输出迭代器的功能,并保留在容器中的位置
双向
组合正向迭代器和逆向迭代器的功能,支持多遍算法
随机访问
组合双向迭代器的功能与直接访问容器中任何元素的功能,即可向前向后跳过任意个元素
<iterator> 中定义了迭代器得使用方法,主要得模版类有:
插入迭代器
插入迭代器是一种迭代器适配器,带有一个容器参数,并生成一个迭代器,用于在指定的容器中插入元素。通过插入迭代器赋值时,迭代器将会插入一个新的元素。C++语言提供了三种插入器,其差别在于插入元素的位置不同:
back_inserter,创建使用push_back实现插入的迭代器,其使用一个对象作为实参将一个新元素插入到容器得后端
front_inserter的操作类似于back_inserter:该函数将创建一个迭代器,调用它所关联的基础容器的push_front成员函数代替赋值操作。
注意:只有当容器提供push_front操作时,才能使用front_inserter。在vector或其他没有push_front运算的容器上使用front_inserter,将产生错误。
inserter使用insert实现插入操作,inserter还带有第二个实参:指向插入起始位置的迭代器,inserter总是在它的迭代器参数所标明的位置前面插入新元素。
流迭代器
虽然iostream类型不是容器,但标准库同样提供了在iostream对象上使用的迭代 器:istream_iterator用于读取读入流,而ostream_iterator用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素 序列。使用流迭代器时,可以用泛型算法从流对象中读数据(或将数据写到流对象中)。
istream_iterator<T> in(strm); 创建从输入流strm中读取T类型对象的istream_iterator对象,strm是一个输入流
istream_iterator<T> in; istream_iterator对象的超出末端迭代器
ostream_iterator<T> out(strm); 创建将T类型的对象写到输出流strm的ostream_iterator对象
ostream_iterator<T> out(strm, delim); 创建将T类型的对象写到输出流strm的ostream_iterator对象,在写入过程中使用delim作为元素的分隔符。delim是以空字符结束的字符数组
流迭代器只定义了最基本的迭代器操作:自增、引用和赋值。此外,可比较两个istream迭代器是否相等(或不等)。而ostream迭代器则不提供比较运算。
流迭代器的限制:
(1)不可能从ostream_iterator对象读入,也不可能写到istream_iterator对象中;
(2)一旦给ostream_iterator对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator对象中每个不同的值都只能正好输出一次。
(3)ostream_iterator没有->操作符。
测试:
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main() {
istream_iterator<int> in_iter(cin);
istream_iterator<int> eof;
//vector<int> vec(in_iter, eof); //do the same work as following loop
vector<int> vec;
while (in_iter != eof)
vec.push_back(*in_iter++); //*in_iter可以取出输入流中得元素
vector<int>::const_iterator it = vec.begin();
for(; it != vec.end(); ++it)
cout<<*it<<endl;
return 0;
}
#include <iostream>
#include <iterator>
using namespace std;
int main() {
ostream_iterator<string> out_iter(cout, ""n");
istream_iterator<string> in_iter(cin), eof;
while (in_iter != eof)
*out_iter++ = *in_iter++;
return 0;
}
反向迭代器
反向迭代器是一种反向遍历容器的迭代器。也就是,从最后一个元素到第一个元素遍历容器。反向迭代器将自增(和自减)的含义反过来了:对于反向迭代器,++运算将访问前一个元素,而--运算则访问下一个元素。
(1)反向迭代器需要使用自减操作符:标准容器上的迭代器(reverse_iterator)既支持自增运算,也支持自减运算。但是,流迭代器由于不能反向遍历流,因此流迭代器不能创建反向迭代器。
(2)可以通过reverse_iterator::base()将反向迭代器转换为普通迭代器使用,从逆序得到普通次序。
测试:
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;
int main() {
string str = "this 'sentence' is a test";
cout<<str<<endl;
string::iterator it1 = find(str.begin(), str.end(), '"'');
string::iterator it2 = find(++it1, str.end(), '"'');
cout<<string(it1, it2)<<endl;
string::reverse_iterator rit1 = find(str.rbegin(), str.rend(), '"'');
string::reverse_iterator rit2 = find(++rit1, str.rend(), '"'');
cout<<string(rit1, rit2)<<endl;
cout<<string(rit2.base(), rit1.base())<<endl;
getchar();
return 0;
}
不同的迭代器支持不同的操作集,而各种算法也要求相应的迭代器具有最小的操作集。因此,可以将算法的迭代器分为下面五类:
输入迭代器
(input iterator) 读,不能写。支持的操作集:==, !=, 前缀++, 后缀++, *, ->。例如,find, accumulate算法要求这类迭代器。
输出迭代器
(output iterator) 写,不能读。支持的操作集:前缀++, 后缀++, *(只能出现在赋值运算的左操作数上)。推出迭代器要求每个迭代器必须正好写入一次。例如,ostream_iterator是输出迭代器,copy算法使用这类迭代器。
前向迭代器(forward iterator) 读和写,支持输入迭代器和输出迭代器提供的所有操作,还支持对同一个元素的多次读写。例如,replace算法需要这种迭代器。
双向迭代器(bidirectional iterator) 读和写,除了支持前向迭代器的所有操作,还支持前缀--和后缀--,即支持双向遍历容器。例如,reverse算法要求这类迭代器。标准库容器中提供的迭代器都至少达到双向迭代器的要求。
随机访问迭代器(random-access iterator) 读和写。提供在常量时间内访问容器任意位置的功能。支持完整的迭代器操作集:1)关系运算:==, !=, <, <=, >, >=;2)算术运算:it + n, it - n, it += n, it -= n以及it1 - it2;3)下标运算:it[n],等价于*(it + n)。需要随机访问迭代器的泛型算法包括sort算法。例如,vector, deque, string迭代器是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。
除了输出迭代器,其他类别的迭代器形成了一个层次结构:需要低级类别迭代器的地方,可使用任意一种更高级的迭代器。例如,对于需要输入迭代器的算法,可传 递前向、双向或随机访问迭代器调用该算法。而反之则不行。注意:向算法传递无效的迭代器类别所引起的错误,无法保证会在编译时被捕获到。
map, set, list类型提供双向迭代器,而string, vector和deque容器上定义的迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。istream_iterator是输 入迭代器,ostream_iterator是输出迭代器。
另外,虽然map和set类型提供双向迭代器,但关联容器只能使用这部分算法的一个子集。因为关联容器的键是const对象。因此,关联容器不能使用任何 写序列元素的算法。只能使用与关联容器绑在一起的迭代器来提供用于读操作的实参。因此,在处理算法时,最好将关联容器上的迭代器视为支持自减运算的输入迭 代器,而不是完整的双向迭代器。
年份 C++标准 俗称
2011 ISO/IEC 14882:2011[2] C++11 也被称为C++0x
2007 ISO/IEC TR 19768:2007[3] C++TR1
2003 ISO/IEC 14882:2003[4] C++03
1998 ISO/IEC 14882:1998[5] C++98
//=============================
c++11新特性
//-----------------------------
auto 关键字
自动帮助推导类型
auto i = 5 // i will be of type int
int n=3;
double pi=3.14;
auto j=pi*n; // j will be of type double
类型更难写的例子
// take a hypothetical Map of ( int and an map(int,int) )
map< int, map<int,int> > _Map;
// see the verbose for defining a const iterator of this map
map<int, map<int,int>>::const_iterator itr1 = _Map.begin();
// now with auto our life gets simplified
const auto itr2 = _Map.begin();
类型更难知晓的例子
template<class U, class V>
void Somefunction(U u, V v)
{
??? result = u*v; // now what would be the type of result ???
// with auto we leave the compiler to determine the type
auto result = u*v;
}
新特性要点总结
①我们可以使用valatile,pointer(*),reference(&),rvalue reference(&&) 来修饰auto
auto k = 5;
auto* pK = new auto(k);
auto** ppK = new auto(&k);
const auto n = 6;
②用auto声明的变量必须初始化
auto m; // m should be intialized
③auto不能与其他类型组合连用
auto int p; // no way
④函数和模板参数不能被声明为auto
void MyFunction(auto parameter){} // no auto as method argument
template<auto T> // utter nonsense - not allowed
void Fun(T t){}
⑤定义在堆上的变量,使用了auto的表达式必须被初始化
int* p = new auto(0); //fine
int* pp = new auto(); // should be initialized
auto x = new auto(); // Hmmm ... no intializer
auto* y = new auto(9); // Fine. Here y is a int*
auto z = new auto(9); //Fine. Here z is a int* (It is not just an int)
⑥以为auto是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其他一些操作,如sizeof和typeid
int value = 123;
auto x2 = (auto)value; // no casting using auto
auto x3 = static_cast<auto>(value); // same as above
⑦定义在一个auto序列的变量必须始终推导成同一类型
auto x1 = 5, x2 = 5.0, x3='r'; // This is too much....we cannot combine like this
⑧auto不能自动推导成CV-qualifiers(constant & volatile qualifiers),除非被声明为引用类型
const int i = 99;
auto j = i; // j is int, rather than const int
j = 100 // Fine. As j is not constant
// Now let us try to have reference
auto& k = i; // Now k is const int&
k = 100; // Error. k is constant
// Similarly with volatile qualifer
⑨auto会退化成指向数组的指针,除非被声明为引用
int a[9];
auto j = a;
cout<<typeid(j).name()<<endl; // This will print int*
auto& k = a;
cout<<typeid(k).name()<<endl; // This will print int [9]
//-----------------------------
decltype
返回值 decltype(表达式)
[返回值的类型是表达式参数的类型]
这个可也用来决定表达式的类型,就像Bjarne暗示的一样,如果我们需要去初始化某种类型的变量,auto是最简单的选择,但是如果我们所需的类型不是一个变量,例如返回值这时我们可也试一下decltype。
现在我们回看一些例子我们先前做过的,
[cpp] view plaincopy
template <class U, class V>
void Somefunction(U u, V v)
{
result = u*v;//now what type would be the result???
decltype(u*v) result = u*v;//Hmm .... we got what we want
}
在下面的一个段落我将会让你熟悉这个观念用 auto 和 decltype 来声明模板函数的返回值,其类型依靠模板参数。
1. 如果这个表达式是个函数,decltype 给出的类型为函数返回值的类型。
[cpp] view plaincopy
int add(int i, int j){ return i+j; }
decltype(add(5,6)) var = 5;//Here the type of var is return of add() -> which is int
2.如果表达式是一个左值类型,那么 decltype 给出的类型为表达式左值引用类型。
[cpp] view plaincopy
struct M { double x; };
double pi = 3.14;
const M* m = new M();
decltype( (m->x) ) piRef = pi;
// Note: Due to the inner bracets the inner statement is evaluated as expression,
// rather than member 'x' and as type of x is double and as this is lvale
// the return of declspec is double& and as 'm' is a const pointer
// the return is actually const double&.
// So the type of piRef is const double&
3.非常重要的标记一下,decltype 不会执行表达式而auto会,他仅仅推论一下表达式的类型。
[cpp] view plaincopy
int foo(){}
decltype( foo() ) x; // x is an int and note that
// foo() is not actually called at runtime
跟踪返回类型:
这对 C++ 开发者来说是一个全新的特性,直到现在函数的返回类型必须放在函数名的前面。到了 C++11,我们也可以将函数返回值的类型放在函数声明后,当然仅需要用 auto 替代返回类型。现在我们想知道怎么做,让我们来寻找答案:
[cpp] view plaincopy
template<class U, class V>
??? Multiply(U u, V v) // how to specifiy the type of the return value
{
return u*v;
}
我们明显的不能像这样:
[cpp] view plaincopy
template<class U, class V>
decltype(u*v) Multiply(U u, V v) // Because u & v are not defined before Multiply.
// What to do...what to do !!!
{
return u*v;
}
这种情况我们可也使用 auto 然后当我们使用 decltype(u*v) 作为返回值这个类型便知晓了.
这是不是很酷?
[cpp] view plaincopy
template<class U, class V>
auto Multiply(U u, V v) -> decltype(u*v) // Note -> after the function bracet.
{
return u*v;
}
//============================
STL算法:
STL中算法大致分为四类:
1、非可变序列算法:指不直接修改其所操作的容器内容的算法。
该算法不对所作用的容器进行修改,包括:
adjacent_find(),find(),find_end(),find_first(),count(),mismatch(),equal(),for_each()和search()等
2、可变序列算法:指可以修改它们所操作的容器内容的算法。
算法对所作用的容器进行修改,包括
copy(),copy_backward() fill() generate() partition() random_shuffle() remove() replace() rotate() reverse() swap() swap_ranges() transfrom() unique()
3、排序算法:包括对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
对容器的内容进行不同方式的排序,包括
sort() stable_sort() partial_sort() partial_sort_copy() nth_element() binary_search() lower_bound() upper_bound() equal_range() merger() includes() push_heap() pop_heap() make_heap() sort_heap() sort_heap() set_union() set_intersection set_difference()
set_symmertric_difference() min() min_element() max() max_element() lexicographical_compare() next_premutation() prev_permutation()
4、数值算法:对容器内容进行数值计算。
对容器的内容进行数值计算,包括
accumulate() innerproduct() partail_sum() adjacent_difference()
//---------------------
非修改性序列操作(12个)
循环
for_each()
对序列中的每个元素执行某操作
查找
find()
在序列中找出某个值的第一次出现的位置
find_if()
在序列中找出符合某谓词的第一个元素
find_end()
在序列中找出一子序列的最后一次出现的位置
find_first_of()
在序列中找出第一次出现指定值集中之值的位置
adjacent_find()
在序列中找出相邻的一对值
计数
count()
在序列中统计某个值出现的次数
count_if()
在序列中统计与某谓词匹配的次数
比较
mismatch()
找出两个序列相异的第一个元素
equal()
两个序列中的对应元素都相同时为真
搜索
search()
在序列中找出一子序列的第一次出现的位置
search_n()
在序列中找出一值的连续n次出现的位置
//---------------------
修改性序列操作(27个)
复制
copy()
从序列的第一个元素起进行复制
copy_backward()
从序列的最后一个元素起进行复制
交换
swap()
交换两个元素
swap_ranges()
交换指定范围的元素
iter_swap()
交换由迭代器所指的两个元素
变换
transform()
将某操作应用于指定范围的每个元素
替换
replace()
用一个给定值替换一些值
replace_if()
替换满足谓词的一些元素
replace_copy()
复制序列时用一给定值替换元素
replace_copy_if()
复制序列时替换满足谓词的元素
填充
fill()
用一给定值取代所有元素
fill_n()
用一给定值取代前n个元素
生成
generate()
用一操作的结果取代所有元素
generate_n()
用一操作的结果取代前n个元素
删除
remove()
删除具有给定值的元素
remove_if()
删除满足谓词的元素
remove_copy()
复制序列时删除具有给定值的元素
remove_copy_if()
复制序列时删除满足谓词的元素
唯一
unique()
删除相邻的重复元素
unique_copy()
复制序列时删除相邻的重复元素
反转
reverse()
反转元素的次序
reverse_copy()
复制序列时反转元素的次序
环移
rotate()
循环移动元素
rotate_copy()
复制序列时循环移动元素
随机
random_shuffle()
采用均匀分布来随机移动元素
划分
partition()
将满足某谓词的元素都放到前面
stable_partition()
将满足某谓词的元素都放到前面并维持原顺序
//---------------------
序列排序及相关操作(27个)
排序
sort()
以很好的平均效率排序
stable_sort()
排序,并维持相同元素的原有顺序
partial_sort()
将序列的前一部分排好序
partial_sort_copy()
复制的同时将序列的前一部分排好序
第n个元素
nth_element()
将第n各元素放到它的正确位置
二分检索
lower_bound()
找到大于等于某值的第一次出现
upper_bound()
找到大于某值的第一次出现
equal_range()
找到(在不破坏顺序的前提下)可插入给定值的最大范围
binary_search()
在有序序列中确定给定元素是否存在
归并
merge()
归并两个有序序列
inplace_merge()
归并两个接续的有序序列
有序结构上的集合操作
includes()
一序列为另一序列的子序列时为真
set_union()
构造两个集合的有序并集
set_intersection()
构造两个集合的有序交集
set_difference()
构造两个集合的有序差集
set_symmetric_difference()
构造两个集合的有序对称差集(并-交)
堆操作
push_heap()
向堆中加入元素
pop_heap()
从堆中弹出元素
make_heap()
从序列构造堆
sort_heap()
给堆排序
最大和最小
min()
两个值中较小的
max()
两个值中较大的
min_element()
序列中的最小元素
max_element()
序列中的最大元素
词典比较
lexicographical_compare()
两个序列按字典序的第一个在前
排列生成器
next_permutation()
按字典序的下一个排列
prev_permutation()
按字典序的前一个排列
//--------------------------------------------实例
STL算法.cpp : 定义控制台应用程序的入口点。
/*******************************************************************************
STL通用算法: Description:
1、非修正序列算法 不对其所作用的容器进行修改
2、修正序列算法 对其所作用的容器进行修改
3、排序算法 对容器的内容进行不同方式的排序
4、数值算法 对容器的内容进行数值计算
*******************************************************************************/
#include "stdafx.h"
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#include <string>
#include <numeric>
using namespace std;
////////////////////////////////////////////////////////////////////////////////////////////////////////////
第一类通用算法---非修正序列算法
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: adjacent_find(first,last)
Description: 搜索重复对
Parameter: 搜索时的起始位置
Return: 返回在该区间第一个重复的对.
By: capter
Date: 2005-12-23
*******************************************************/
int _tmain(int argc, _TCHAR* argv[])
{
multiset<int> intset;
intset.insert(10);
intset.insert(3);
intset.insert(1);
intset.insert(3);
intset.insert(8);
intset.insert(8);
intset.insert(5);
//显示该多重集合
multiset<int>::iterator iter;
for(iter=intset.begin(); iter!=intset.end(); iter++)
cout<<*iter<<" ";
cout<<endl;
//查找第一个相等的值
iter = adjacent_find(intset.begin(),intset.end());
cout<<*iter<<endl;
iter++;
cout<<*iter<<endl;
return 0;
}
/*******************************************************
Function: count(first,last,val)
Description: 计算val出现的次数
Parameter: 搜索时的起始位置和要计算的值
Return: 返回出现的次数
By: capter
Date: 2005-12-23
*******************************************************/
int main()
{
multiset<int> intset;
intset.insert(10);
intset.insert(6);
intset.insert(1);
intset.insert(3);
intset.insert(6);
intset.insert(2);
intset.insert(3);
//显示该多重集合的值
multiset<int>::iterator iter;
for(iter=intset.begin(); iter!=intset.end(); iter++)
cout<<*iter<<" ";
cout<<endl;
//搜索数字3出现的次数
int n = count(intset.begin(),intset.end(),3);
cout<<"数字3在该多重集合中共出现了:"<<n<<"次"<<endl;
return 0;
}
/*******************************************************
Function: for_each(first,last,func)
Description: 对first,last范围内每个元素执行func定义的函数
Parameter: first,last要执行元素的范围,func自己定义的函数
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
int main()
{
multiset<int> intset;
intset.insert(10);
intset.insert(6);
intset.insert(1);
intset.insert(3);
intset.insert(6);
intset.insert(2);
intset.insert(3);
//显示该多重集合的值
for_each(intset.begin(),intset.end(),showvalue);
cout<<endl;
return 0;
}
//////////////////////////////////////////////////
第一类--非修正序列算法还有其他函数
equal(first,last,first2)
find(first,last,val)
find_end(first,last,first2,last2)
find_first(first,last,first2,last2)
mismatch(first,last,first2)
search(first,last,first2,last2)
//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
第二类通用算法---修正序列算法
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: fill(first,last,val)
Description: 把val的值赋给first,last中所有的元素
Parameter: 起始位置和要赋的值
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> intvector;
for(int x=0;x<10;x++)
intvector.push_back(x);
//显示该向量的内容
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
//填充该值
fill(intvector.begin(),intvector.begin()+5,0);
//显示填充后的值
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
return 0;
}
/*******************************************************
Function: random_shuffle(first,last)
Description: 在指示器first,last中随机排列元素
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> intvector;
for(int x=0;x<10;x++)
intvector.push_back(x);
//显示该向量的值
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
//对该向量进行随机排序
random_shuffle(intvector.begin(),intvector.end());
//显示随机排序后的值
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
return 0;
}
/*******************************************************
Function: partition(first,last,pred)
Description: 在指示器first,last中经过谓词的判断后一分为二
Parameter: 起始位置和谓词
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(int x)
{
cout<<x<<" ";
}
//谓词函数
bool equals5(int val)
{
return (val == 5);
}
int main()
{
vector<int> intvector;
intvector.push_back(8);
intvector.push_back(5);
intvector.push_back(7);
intvector.push_back(5);
intvector.push_back(2);
intvector.push_back(5);
//显示该向量的内容
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
//对该向量进行分段
partition(intvector.begin(),intvector.end(),equals5);
//显示新内容
for_each(intvector.begin(),intvector.end(),showvalue);
cout<<endl;
return 0;
}
/*******************************************************
Function: rotate(first,middle,last)
Description: 把从middle到last的元素旋转到first范围处
Parameter: 起始位置和开始旋转位置
By: capter
Date: 2005-12-23
*******************************************************/
void showvalue(char x)
{
cout<<x<<" ";
}
int main()
{
vector<char> charvector;
for(int i=0;i<10;i++)
charvector.push_back(65+i);
//显示向量内容
for_each(charvector.begin(),charvector.end(),showvalue);
cout<<endl;
//旋转
rotate(charvector.begin(),charvector.begin()+6,charvector.end());
//显示旋转后的内容
for_each(charvector.begin(),charvector.end(),showvalue);
cout<<endl;
return 0;
}
//////////////////////////////////////////////////
copy(first,last,first2)
copy_backward(first,last,first2)
generate(first,last,func)
remove(first,last,val)
replace(first,last,val1,val2)
reverse(first,last)
swap(it1,it2)
swap_ranges(first,last,first2)
transform(first,last,first2,func)
unique(first,last)
//////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
第三类通用算法---排序算法
/////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: sort(first,last)
Description: 排序
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void show(char val)
{
cout<<val<<" ";
}
int main()
{
vector<char> charvector;
charvector.push_back('Z');
charvector.push_back('D');
charvector.push_back('F');
charvector.push_back('S');
charvector.push_back('A');
charvector.push_back('Q');
charvector.push_back('C');
charvector.push_back('G');
charvector.push_back('M');
charvector.push_back('Y');
//显示向量
for_each(charvector.begin(),charvector.end(),show);
cout<<endl;
//排序
sort(charvector.begin(),charvector.end());
//显示排序后的向量
for_each(charvector.begin(),charvector.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: partial_sort(first,middle,last)
Description: 进行偏序排序
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void show(string val)
{
cout<<val<<endl;
}
int main()
{
vector<string> strvector;
strvector.push_back("zebra");
strvector.push_back("deer");
strvector.push_back("fish");
strvector.push_back("snake");
strvector.push_back("bat");
strvector.push_back("cat");
strvector.push_back("bird");
strvector.push_back("turtle");
strvector.push_back("horse");
strvector.push_back("cow");
//显示向量内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
//进行偏序排序
partial_sort(strvector.begin(),strvector.begin()+5,strvector.end());
//显示排序后的内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: nth_element(first,nth,last)
Description: 排序
Parameter: 起始位置
By: capter
Date: 2005-12-23
*******************************************************/
void show(string val)
{
cout<<val<<endl;
}
int main()
{
vector<string> strvector;
strvector.push_back("zebra");
strvector.push_back("deer");
strvector.push_back("fish");
strvector.push_back("snake");
strvector.push_back("bat");
strvector.push_back("cat");
strvector.push_back("bird");
strvector.push_back("turtle");
strvector.push_back("horse");
strvector.push_back("cow");
//显示向量内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
//进行偏序排序
nth_element(strvector.begin(),strvector.begin()+5,strvector.end());
//显示排序后的内容
for_each(strvector.begin(),strvector.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: merge(first,last,first2,last2,result)
Description: 合并排序
Parameter: 起始位置和结果集
By: capter
Date: 2005-12-23
*******************************************************/
void show(string val)
{
cout<<val<<endl;
}
int main()
{
vector<string> strvector1,strvector2;
vector<string> strvector3(10);
strvector1.push_back("zebra");
strvector1.push_back("deer");
strvector1.push_back("fish");
strvector1.push_back("snake");
strvector1.push_back("bat");
strvector2.push_back("cat");
strvector2.push_back("bird");
strvector2.push_back("turtle");
strvector2.push_back("horse");
strvector2.push_back("cow");
//显示向量内容
for_each(strvector1.begin(),strvector1.end(),show);
cout<<endl;
//显示排序后的内容
for_each(strvector2.begin(),strvector2.end(),show);
cout<<endl;
sort(strvector1.begin(),strvector1.end());
sort(strvector2.begin(),strvector2.end());
merge(strvector1.begin(),strvector1.end(),strvector2.begin(),strvector2.end(),strvector3.begin());
//显示排序后的结果
for_each(strvector3.begin(),strvector3.end(),show);
cout<<endl;
return 0;
}
/////////////////////////////////////////////////////////////////////
第二种通用算法还有以下几种
binary_search(first,last,val)
equal_range(first,last,val)
includes(first,last,first2,last2)
lexicographical_compare(first,last,first2,last2)
lower_bound(first,last,val)
make_heap(first,last)
max(val1,val2)
max_element(first,last)
min(val1,val2)
next_permutation(first,last)
partial_sort_copy(first,last,first2,last2);
pop_heap(first,last)
prev_permutation(first,last)
push_heap(first,last)
set_difference(first,last,first2,last2,result)
set_intersection(first,last,first2,last2,result)
set_symmetric_difference(first,last,first2,last2,result)
set_union(first,last,first2,last2,result)
sort(first,last)
sort_heap(first,last)
stable_sort(first,last)
upper_bound(first,last,val)
////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第四种算法---数值算法
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************
Function: accumulate(first,last,init)
Description: 求和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> intvector;
for(int x=0; x<5; ++x)
intvector.push_back(x);
//显示内容
for_each(intvector.begin(),intvector.end(),show);
//求和
int result = accumulate(intvector.begin(),intvector.end(),5);
cout<<result<<endl;
return 0;
}
/*******************************************************
Function: inner_product(first,last,first2,init)
Description: 两向量对应的值相加,然后再求和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> vector1,vector2;
for(int i=0;i<5;i++)
vector1.push_back(i);
for(int i=2;i<7;i++)
vector2.push_back(i);
for_each(vector1.begin(),vector1.end(),show);
cout<<endl;
for_each(vector2.begin(),vector2.end(),show);
cout<<endl;
int result = inner_product(vector1.begin(),vector1.end(),vector2.begin(),0);
cout<<result<<endl;
return 0;
}
/*******************************************************
Function: partial_sum(first,last,first2,init)
Description: 求部分和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> vector1;
vector<int> vector2(5);
for(int i=2;i<7;++i)
vector1.push_back(i);
//显示向量内容
for_each(vector1.begin(),vector1.end(),show);
cout<<endl;
//求部分和
partial_sum(vector1.begin(),vector1.end(),vector2.begin());
//显示求和后的结果
for_each(vector2.begin(),vector2.end(),show);
cout<<endl;
return 0;
}
/*******************************************************
Function: adjacent_difference(first,last,first2,result)
Description: 两向量对应的值相加,然后再求和
Parameter: 起始位置和初始参数
Return: 结果
By: capter
Date: 2005-12-23
*******************************************************/
void show(int x)
{
cout<<x<<" ";
}
int main()
{
vector<int> vector1;
vector<int> vector2(5);
vector1.push_back(3);
vector1.push_back(4);
vector1.push_back(12);
vector1.push_back(6);
vector1.push_back(10);
显示向量内容
for_each(vector1.begin(),vector1.end(),show);
cout<<endl;
求部分差
adjacent_difference(vector1.begin(),vector1.end(),vector2.begin());
显示求和后的结果
for_each(vector2.begin(),vector2.end(),show);
cout<<endl;
return 0;
}
C++STL 常用算法,使用时包含#include <algorithm>
一、非变异算法
是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理、元素查找、子序列搜索、统计和匹配。非变异算法具有极为广泛的适用性,基本上可应用与各种容器。
1查找容器元素find
它用于查找等于某值的元素。它在迭代器区间[first,last)(闭开区间)上查找等于value值的元素,如果迭代器i所指的元素满足*i=value,则返回迭代器i;未找到满足条件的元素,返回last。函数原型:find( v1.begin(), v1.end(), num_to_find );
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
int num_to_find = 6;
vector<int> v1;
for( int i = 0; i < 10; i++ )
v1.push_back(2*i);
vector<int>::iterator result;
result = find( v1.begin(), v1.end(), num_to_find );
if( result == v1.end() )
cout << "未找到任何元素匹配 " << num_to_find << endl;
else
cout << "匹配元素的索引值是 " << result-v1.begin() << endl;
}
2条件查找容器元素find_if
利用返回布尔值的谓词判断pred,检查迭代器区间[first,last)(闭开区间)上的每一个元素,如果迭代器i满足pred(*i)=true,表示找到元素并返回迭代值i(找到的第一个符合条件的元素);未找到元素,返回末位置last。函数原型:find_if(v.begin(),v.end(),divby5);
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool divby5(int x)
{
return x%5?0:1;
}
void main()
{
vector<int> v(20);
for(int i=0;i<v.size();i++)
{
v[i]=(i+1)*(i+3);
cout<<v[i]<<' ';
}
cout<<endl;
vector<int>::iterator ilocation;
ilocation=find_if(v.begin(),v.end(),divby5);
if(ilocation!=v.end())
cout<<"找到第一个能被5整除的元素:"<<*ilocation<<endl<<"元素的索引位置是: "<<ilocation-v.begin()<<endl;
}
3统计等于某值的容器元素个数count
list<int> l;
count(l.begin(),l.end(),value)
4条件统计count_if
count_if(l.begin(),l.end(),pred)。谓词pred含义同find_if中的谓词。例子可以参考例2.
5子序列搜索search
search算法函数在一个序列中搜索与另一序列匹配的子序列。参数分别为一个序列的开始位置,结束位置和另一个序列的开始,结束位置。
函数原型:search(v1.begin(),v1.end(),v2.begin(),v2.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v1;
cout<<"v1:";
for(int i=0;i<5;i++)
{
v1.push_back(i+5);
//注意:v1定义时没有给定大小,因此这里不能直接使用赋值语句。
cout<<v1[i]<<' ';
}
cout<<endl;
vector<int> v2;
cout<<"v2:";
for(i=0;i<2;i++)
{
v2.push_back(i+7);
cout<<v2[i]<<' ';
}
cout<<endl;
vector<int>::iterator ilocation;
ilocation=search(v1.begin(),v1.end(),v2.begin(),v2.end());
if(ilocation!=v1.end())
cout<<"v2的元素包含在v1中,起始元素为"<<"v1["<<ilocation-v1.begin()<<']'<<endl;
else
cout<<"v2的元素不包含在v1中"<<endl;
}
6重复元素子序列搜索search_n
search_n算法函数搜索序列中是否有一系列元素值均为某个给定值的子序列。函数原型:search_n(v.begin(),v.end(),3,8),在v中找到3个连续的元素8
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(1);
v.push_back(8);
v.push_back(8);
v.push_back(8);
v.push_back(6);
v.push_back(6);
v.push_back(8);
vector<int>::iterator i;
i=search_n(v.begin(),v.end(),3,8);
if(i!=v.end())
cout<<"在v中找到3个连续的元素8"<<endl;
else
cout<<"在v中未找到3个连续的元素8"<<endl;
}
7最后一个子序列搜索find_end
函数原型find_end(v1.begin(),v1.end(),v2.begin(),v2.end());在V1中要求的位置查找V2中要求的序列。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v1;
v1.push_back(-5);
v1.push_back(1);
v1.push_back(2);
v1.push_back(-6);
v1.push_back(-8);
v1.push_back(1);
v1.push_back(2);
v1.push_back(-11);
vector<int> v2;
v2.push_back(1);
v2.push_back(2);
vector<int>::iterator i;
i=find_end(v1.begin(),v1.end(),v2.begin(),v2.end());
if(i!=v1.end())
cout<<"v1中找到最后一个匹配v2的子序列,位置在" <<"v1["<<i-v1.begin()<<"]"<<endl;
}
二、变异算法
是一组能够修改容器元素数据的模板函数。copy(v.begin(),v.end(),l.begin());将v中的元素复制到l中。
1元素复制copy
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(5);
list<int> l;
l.push_back(2);
l.push_back(4);
l.push_back(6);
l.push_back(8);
l.push_back(10);
copy(v.begin(),v.end(),l.begin());
list<int>::iterator i;
for(i=l.begin();i!=l.end();i++)
cout<<*i<<' ';
cout<<endl;
}
2元素变换transform改变
函数原型:transform(v.begin(),v.end(),l.begin(),square);也是复制,但是要按某种方案复制。
#include <vector>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;
int square(int x)
{
return x*x;
}
void main()
{
vector<int> v;
v.push_back(5);
v.push_back(15);
v.push_back(25);
list<int> l(3);
transform(v.begin(),v.end(),l.begin(),square);
list<int>::iterator i;
for(i=l.begin();i!=l.end();i++)
cout<<*i<<' ';
cout<<endl;
}
3替换replace
replace算法将指定元素值替换为新值。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(13);
v.push_back(25);
v.push_back(27);
v.push_back(25);
v.push_back(29);
replace(v.begin(),v.end(),25,100);
vector<int>::iterator i;
for(i=v.begin();i!=v.end();i++)
cout<<*i<<' ';
cout<<endl;
}
输出结果为13 100 27 100 29
4条件替换replace_if
函数原型:replace_if(v.begin(),v.end(),odd,100);
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool odd(int x)
{
return x%2;
}
void main()
{
vector<int> v;
for(int i=1;i<10;i++)
v.push_back(i);
replace_if(v.begin(),v.end(),odd,100);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
5n次填充fill_n
函数原型fill_n(v.begin(),5,-1);向从v.begin开始的后面5个位置跳入-1
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v(10);
fill_n(v.begin(),5,-1);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
输出结果:-1 -1 -1 -1 -1 0 0 0 0 0
6随机生成n个元素generate
函数原型:generate_n(v.begin(),5,rand);向从v.begin开始的后面5个位置随机填写数据。
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v(10);
generate_n(v.begin(),5,rand);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
7条件移除remove_if
返回值相当于移除满足条件的元素后形成的新向量的end()值。
函数原型:remove_if(v.begin(),v.end(),even);
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool even(int x)
{
return x%2?0:1;
}
void main()
{
vector<int> v;
for(int i=1;i<=10;i++)
v.push_back(i);
vector<int>::iterator ilocation,result;
cout<<"移除前:";
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
result=remove_if(v.begin(),v.end(),even);
cout<<"移除后:";
for(ilocation=v.begin();ilocation!=result;ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
8剔除连续重复元素unique
函数原型:unique(v.begin(),v.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(2);
v.push_back(6);
v.push_back(6);
v.push_back(6);
v.push_back(9);
v.push_back(6);
v.push_back(3);
vector<int>::iterator ilocation,result;
result=unique(v.begin(),v.end());
for(ilocation=v.begin();ilocation!=result;ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
输出结果:2 6 9 6 3
三、排序算法
1、创建堆make_heap
2、元素入堆push_heap(默认插入最后一个元素)
3、元素出堆pop_heap(与push_heap一样,pop_heap必须对堆操作才有意义)
#include <vector>??????
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(5);
v.push_back(6);
v.push_back(4);
v.push_back(8);
v.push_back(2);
v.push_back(3);
v.push_back(7);
v.push_back(1);
v.push_back(9);
make_heap(v.begin(),v.end());
v.push_back(20);
push_heap(v.begin(),v.end());
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
pop_heap(v.begin(),v.end());
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
4堆排序sort_heap
使用:
make_heap(v.begin(),v.end());
sort_heap(v.begin(),v.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(3);
v.push_back(9);
v.push_back(6);
v.push_back(3);
v.push_back(17);
v.push_back(20);
v.push_back(12);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
make_heap(v.begin(),v.end());
sort_heap(v.begin(),v.end());
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
输出结果:
3 9 6 3 17 20 12
3 3 6 9 12 17 20
5排序sort
函数原型:sort(v.begin(),v.end());
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void main()
{
vector<int> v;
v.push_back(2);
v.push_back(8);
v.push_back(-15);
v.push_back(90);
v.push_back(26);
v.push_back(7);
v.push_back(23);
v.push_back(30);
v.push_back(-27);
v.push_back(39);
v.push_back(55);
vector<int>::iterator ilocation;
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
sort(v.begin(),v.end());//比较函数默认
for(ilocation=v.begin();ilocation!=v.end();ilocation++)
cout<<*ilocation<<' ';
cout<<endl;
}
//============================
STL容器
test.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <stack>
using namespace std;
//向量类模板
int main()
{
std::vector<char> charvector;
int x = 0;
for(int i=0; i<10;i++)
charvector.push_back(65 + i);
std::vector<char>::iterator iter;
for(iter=charvector.begin();iter!=charvector.end();iter++)
{
cout<<"Element #"<<x++<<" : "<<*iter<<endl;
}
cout<<"当前数组的个数为:"<<charvector.size()<<endl;
vector<char>::iterator start = charvector.begin();
charvector.insert(start,5,'x');
cout<<"after insert :"<<endl;
for(iter=charvector.begin();iter!=charvector.end();iter++)
cout<<*iter;
cout<<endl;
cout<<"after delete :"<<endl;
int size=charvector.size();
for(int i=0;i<size;i++)
{
vector<char>::iterator start = charvector.begin();
charvector.erase(start);
vector<char>::iterator iter1;
for(iter1=charvector.begin();iter1!=charvector.end();iter1++)
cout<<*iter1;
cout<<endl;
}
return 0;
}
//双端队列类模板
int main()
{
deque<char> chardeque;
for(int i=0;i<10;++i)
chardeque.push_front(65+i);
int size=chardeque.size();
deque<char>::iterator iter;
for(iter=chardeque.begin();iter!=chardeque.end();iter++)
cout<<*iter;
for(int i=0;i<size;i++)
{
chardeque.pop_back();
for(iter=chardeque.begin();iter!=chardeque.end();iter++)
cout<<*iter;
cout<<endl;
}
return 0;
}
//链表类模板
int main()
{
list<char> charlist;
int x=0;
for(int i=0;i<10;i++)
charlist.push_front(65+i);
list<char>::iterator iter;
for(iter=charlist.begin();iter!=charlist.end();iter++)
cout<<*iter;
cout<<endl;
list<char>::iterator start=charlist.begin();
charlist.insert(++start,5,'x');
for(iter=charlist.begin();iter!=charlist.end();iter++)
cout<<*iter;
cout<<endl;
return 0;
}
//容器适配器stack
int main()
{
stack<int,list<int> > intstack;
for(int x=1;x<=10;x++)
{
intstack.push(x*100);
}
int size=intstack.size();
for(int i=0;i<size;i++)
{
cout<<intstack.top()<<endl;
intstack.pop();
}
return 0;
}
//容器适配器queue
int main()
{
queue<int,list<int> > intqueue;
for(int x=1; x<=10; x++)
{
intqueue.push(x*100);
}
int size = intqueue.size();
for(int i=0;i<size;i++)
{
cout<<"intqueue "<<intqueue.front()<<endl;
intqueue.pop();
}
return 0;
}
//优先级队列
int main()
{
std::priority_queue<int, std::vector<int>,std::greater<int> > intp_queue;
intp_queue.push(400);
intp_queue.push(100);
intp_queue.push(500);
intp_queue.push(300);
intp_queue.push(200);
int size = intp_queue.size();
for(int i=0; i<size; i++)
{
cout<<" "<<intp_queue.top()<<endl;
intp_queue.pop();
}
cout<<endl;
return 0;
}
//集合
int main()
{
set<int> intset;//升序
intset.insert(10);
intset.insert(5);
intset.insert(1);
intset.insert(3);
intset.insert(8);
set<int>::iterator iter;
for(iter=intset.begin();iter!=intset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
cout<<"after delete :"<<endl;
set<int>::iterator start;
start=intset.begin();
intset.erase(start++);
for(iter=intset.begin();iter!=intset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
cout<<"find data in set"<<endl;
iter = intset.find(5);
if(iter == intset.end())
cout<<"can't find 5"<<endl;
else
cout<<"ok,find the 5"<<endl;
return 0;
}
//多重数据集
int main()
{
multiset<int> intmset;
intmset.insert(10);
intmset.insert(5);
intmset.insert(1);
intmset.insert(3);
intmset.insert(8);
intmset.insert(5);
intmset.insert(8);
multiset<int>::iterator iter;
for(iter=intmset.begin();iter!=intmset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
iter=intmset.begin();
intmset.erase(++iter);
for(iter=intmset.begin();iter!=intmset.end();iter++)
cout<<*iter<<" ";
cout<<endl;
iter=intmset.find(3);
if(iter==intmset.end())
cout<<"sorry,it's error !"<<endl;
else
cout<<"It's find the 3"<<endl;
return 0;
}
//映射
int main()
{
map<int,char> charmap;
charmap.insert(map<int,char>::value_type(1,'A'));
charmap.insert(map<int,char>::value_type(5,'B'));
charmap.insert(map<int,char>::value_type(2,'C'));
charmap.insert(map<int,char>::value_type(3,'D'));
charmap.insert(map<int,char>::value_type(4,'E'));
map<int,char>::iterator iter;
for(iter=charmap.begin();iter!=charmap.end();iter++)
cout<<(*iter).first<<"--"<<(*iter).second<<" ";
cout<<endl;
cout<<"after delete :"<<endl;
iter = charmap.begin();
charmap.erase(++iter);
for(iter=charmap.begin();iter!=charmap.end();iter++)
cout<<(*iter).first<<"--"<<(*iter).second<<" ";
cout<<endl;
std::map<int ,char>::iterator i=charmap.find(4);
if(i==charmap.end())
cout<<"sorry,can't find"<<endl;
else
cout<<"ok,it's find"<<endl;
return 0;
}
//位集合
void display(std::bitset<8> bs)
{
cout<<"bitset = ";
for(int i=0;i<8;i++)
cout<<bs[i];
cout<<endl;
}
int main()
{
bitset<8> bitset;
display(bitset);
cout<<"set bits 1,2,3,5,7"<<endl;
bitset.set(1);
bitset.set(2);
bitset.set(3);
bitset.set(5);
bitset.set(7);
display(bitset);
cout<<"reset bits 2,3"<<endl;
bitset.reset(2);
bitset.reset(3);
display(bitset);
for(int i=0;i<8;i++)
{
cout<<"bit "<<i<<" is ";
if(bitset.test(i))//位的测试
cout<<"set"<<endl;
else
cout<<"unset"<<endl;
}
return 0;
}
//------------容器使用实例
只有顺序容器和关联容器支持迭代器遍历,各容器支持的迭代器的类别如下:
容器
支持的迭代器类别
说明
vector
随机访问
一种随机访问的数组类型,提供了对数组元素进行快速随机访问以及在序列尾部进行快速的插入和删除操作的功能。可以再需要的时候修改其自身的大小
deque
随机访问
一种随机访问的数组类型,提供了序列两端快速进行插入和删除操作的功能。可以再需要的时候修改其自身的大小
list
双向
一种不支持随机访问的数组类型,插入和删除所花费的时间是固定的,与位置无关。
set
双向
一种随机存取的容器,其关键字和数据元素是同一个值。所有元素都必须具有惟一值。
multiset
双向
一种随机存取的容器,其关键字和数据元素是同一个值。可以包含重复的元素。
map
双向
一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个特定的关键字只能与一个元素关联。
multimap
双向
一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个关键字可以与多个数据元素关联。
stack
不支持
适配器容器类型,用vector,deque或list对象创建了一个先进后出容器
queue
不支持
适配器容器类型,用deque或list对象创建了一个先进先出容器
priority_queue
不支持
适配器容器类型,用vector或deque对象创建了一个排序队列
下面列举了些例子说明各个容器的用法:
1、vector
#include <iostream>
#include <vector>
int main()
{
std::vector<char> charVector;
int x;
for (x=0; x<10; ++x)
charVector.push_back(65 + x);
int size = charVector.size();
for (x=0; x<size; ++x)
{
std::vector<char>::iterator start =
charVector.begin();
charVector.erase(start);
std::vector<char>::iterator iter;
for (iter = charVector.begin();
iter != charVector.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
}
return 0;
}
2、deque
#include <iostream>
#include <deque>
int main()
{
std::deque<char> charDeque;
int x;
for (x=0; x<10; ++x)
charDeque.push_front(65 + x);
int size = charDeque.size();
for (x=0; x<size; ++x)
{
std::deque<char>::iterator start =
charDeque.begin();
charDeque.erase(start);
std::deque<char>::iterator iter;
for (iter = charDeque.begin();
iter != charDeque.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
}
return 0;
}
3、list
#include <iostream>
#include <list>
int main()
{
// Create and populate the list.
int x;
std::list<char> charList;
for (x=0; x<10; ++x)
charList.push_front(65 + x);
// Display contents of list.
std::cout << "Original list: ";
std::list<char>::iterator iter;
for (iter = charList.begin();
iter != charList.end(); iter++)
{
std::cout << *iter;
//char ch = *iter;
//std::cout << ch;
}
std::cout << std::endl;
// Insert five Xs into the list.
std::list<char>::iterator start = charList.begin();
charList.insert(++start, 5, 'X');
// Display the result.
std::cout << "Resultant list: ";
for (iter = charList.begin();
iter != charList.end(); iter++)
{
std::cout << *iter;
//char ch = *iter;
//std::cout << ch;
}
return 0;
}
4、set
#include <iostream>
#include <set>
int main()
{
// Create the set object.
std::set<char> charSet;
// Populate the set with values.
charSet.insert('E');
charSet.insert('D');
charSet.insert('C');
charSet.insert('B');
charSet.insert('A');
// Display the contents of the set.
std::cout << "Contents of set: " << std::endl;
std::set<char>::iterator iter;
for (iter = charSet.begin(); iter != charSet.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Find the D.
iter = charSet.find('D');
if (iter == charSet.end())
std::cout << "Element not found.";
else
std::cout << "Element found: " << *iter;
return 0;
}
5、multiset
#include <iostream>
#include <set>
int main()
{
// Create the first set object.
std::multiset<char> charMultiset1;
// Populate the multiset with values.
charMultiset1.insert('E');
charMultiset1.insert('D');
charMultiset1.insert('C');
charMultiset1.insert('B');
charMultiset1.insert('A');
charMultiset1.insert('B');
charMultiset1.insert('D');
// Display the contents of the first multiset.
std::cout << "Contents of first multiset: " << std::endl;
std::multiset<char>::iterator iter;
for (iter = charMultiset1.begin();
iter != charMultiset1.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Create the second multiset object.
std::multiset<char> charMultiset2;
// Populate the multiset with values.
charMultiset2.insert('J');
charMultiset2.insert('I');
charMultiset2.insert('H');
charMultiset2.insert('G');
charMultiset2.insert('F');
charMultiset2.insert('G');
charMultiset2.insert('I');
// Display the contents of the second multiset.
std::cout << "Contents of second multiset: "
<< std::endl;
for (iter = charMultiset2.begin();
iter != charMultiset2.end(); iter++)
std::cout << *iter << std::endl;
std::cout << std::endl;
// Compare the sets.
if (charMultiset1 == charMultiset2)
std::cout << "set1 == set2";
else if (charMultiset1 < charMultiset2)
std::cout << "set1 < set2";
else if (charMultiset1 > charMultiset2)
std::cout << "set1 > set2";
return 0;
}
6、map
#include <iostream>
#include <map>
typedef std::map<int, char> MYMAP;
int main()
{
// Create the first map object.
MYMAP charMap1;
// Populate the first map with values.
charMap1[1] = 'A';
charMap1[4] = 'D';
charMap1[2] = 'B';
charMap1[5] = 'E';
charMap1[3] = 'C';
// Display the contents of the first map.
std::cout << "Contents of first map: " << std::endl;
MYMAP::iterator iter;
for (iter = charMap1.begin();
iter != charMap1.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Create the second map object.
MYMAP charMap2;
// Populate the first map with values.
charMap2[1] = 'F';
charMap2[4] = 'I';
charMap2[2] = 'G';
charMap2[5] = 'J';
charMap2[3] = 'H';
// Display the contents of the second map.
std::cout << "Contents of second map: " << std::endl;
for (iter = charMap2.begin();
iter != charMap2.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Compare the maps.
if (charMap1 == charMap2)
std::cout << "map1 == map2";
else if (charMap1 < charMap2)
std::cout << "map1 < map2";
else if (charMap1 > charMap2)
std::cout << "map1 > map2";
return 0;
}
7、multimap
#include <iostream>
#include <map>
typedef std::multimap<int, char> MYMAP;
int main()
{
// Create the first multimap object.
MYMAP charMultimap;
// Populate the multimap with values.
charMultimap.insert(MYMAP::value_type(1,'A'));
charMultimap.insert(MYMAP::value_type(4,'C'));
charMultimap.insert(MYMAP::value_type(2,'B'));
charMultimap.insert(MYMAP::value_type(7,'E'));
charMultimap.insert(MYMAP::value_type(5,'D'));
charMultimap.insert(MYMAP::value_type(3,'B'));
charMultimap.insert(MYMAP::value_type(6,'D'));
// Display the contents of the first multimap.
std::cout << "Contents of first multimap: " << std::endl;
MYMAP::iterator iter;
for (iter = charMultimap.begin();
iter != charMultimap.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Create the second multimap object.
MYMAP charMultimap2;
// Populate the second multimap with values.
charMultimap2.insert(MYMAP::value_type(1,'C'));
charMultimap2.insert(MYMAP::value_type(4,'F'));
charMultimap2.insert(MYMAP::value_type(2,'D'));
charMultimap2.insert(MYMAP::value_type(7,'E'));
charMultimap2.insert(MYMAP::value_type(5,'F'));
charMultimap2.insert(MYMAP::value_type(3,'E'));
charMultimap2.insert(MYMAP::value_type(6,'G'));
// Display the contents of the second multimap.
std::cout << "Contents of second multimap: " << std::endl;
for (iter = charMultimap2.begin();
iter != charMultimap2.end(); iter++)
{
std::cout << (*iter).first << " --> ";
std::cout << (*iter).second << std::endl;
}
std::cout << std::endl;
// Compare the multimaps.
if (charMultimap == charMultimap2)
std::cout << "multimap1 == multimap2";
else if (charMultimap < charMultimap2)
std::cout << "multimap1 < multimap2";
else if (charMultimap > charMultimap2)
std::cout << "multimap1 > multimap2";
return 0;
}
8、stack
#include <iostream>
#include <list>
#include <stack>
int main()
{
std::stack<int, std::list<int> > intStack;
int x;
std::cout << "Values pushed onto stack:"
<< std::endl;
for (x=1; x<11; ++x)
{
intStack.push(x*100);
std::cout << x*100 << std::endl;
}
std::cout << "Values popped from stack:"
<< std::endl;
int size = intStack.size();
for (x=0; x<size; ++x)
{
std::cout << intStack.top() << std::endl;
intStack.pop();
}
return 0;
}
9、queue
#include <iostream>
#include <list>
#include <queue>
int main()
{
std::queue<int, std::list<int> > intQueue;
int x;
std::cout << "Values pushed onto queue:"
<< std::endl;
for (x=1; x<11; ++x)
{
intQueue.push(x*100);
std::cout << x*100 << std::endl;
}
std::cout << "Values removed from queue:"
<< std::endl;
int size = intQueue.size();
for (x=0; x<size; ++x)
{
std::cout << intQueue.front() << std::endl;
intQueue.pop();
}
return 0;
}
10、priority_queue
#include <iostream>
#include <list>
#include <queue>
int main()
{
std::priority_queue<int, std::vector<int>,std::greater<int> > intPQueue;
int x;
intPQueue.push(400);
intPQueue.push(100);
intPQueue.push(500);
intPQueue.push(300);
intPQueue.push(200);
std::cout << "Values removed from priority queue:"
<< std::endl;
int size = intPQueue.size();
for (x=0; x<size; ++x)
{
std::cout << intPQueue.top() << std::endl;
intPQueue.pop();
}
return 0;
}
//====================================================
STL 迭代器
标准模板库(The Standard Template Library, STL)定义了五种迭代器。下面的图表画出了这几种:
input output
\ /
forward
|
bidirectional
|
random access
要注意,上面这图表并不是表明它们之间的继承关系:而只是描述了迭代器的种类和接口。处于图表下层的迭代器都是相对于处于图表上层迭代器的扩张集。例如:forward迭代器不但拥有input和output迭代器的所有功能,还拥有更多的功能。
各个迭代器的功能如下:
迭代器类别
说明
输入
从容器中读取元素。输入迭代器只能一次读入一个元素向前移动,输入迭代器只支持一遍算法,同一个输入迭代器不能两遍遍历一个序列
输出
向容器中写入元素。输出迭代器只能一次一个元素向前移动。输出迭代器只支持一遍算法,统一输出迭代器不能两次遍历一个序列
正向
组合输入迭代器和输出迭代器的功能,并保留在容器中的位置
双向
组合正向迭代器和逆向迭代器的功能,支持多遍算法
随机访问
组合双向迭代器的功能与直接访问容器中任何元素的功能,即可向前向后跳过任意个元素
<iterator> 中定义了迭代器得使用方法,主要得模版类有:
插入迭代器
插入迭代器是一种迭代器适配器,带有一个容器参数,并生成一个迭代器,用于在指定的容器中插入元素。通过插入迭代器赋值时,迭代器将会插入一个新的元素。C++语言提供了三种插入器,其差别在于插入元素的位置不同:
back_inserter,创建使用push_back实现插入的迭代器,其使用一个对象作为实参将一个新元素插入到容器得后端
front_inserter的操作类似于back_inserter:该函数将创建一个迭代器,调用它所关联的基础容器的push_front成员函数代替赋值操作。
注意:只有当容器提供push_front操作时,才能使用front_inserter。在vector或其他没有push_front运算的容器上使用front_inserter,将产生错误。
inserter使用insert实现插入操作,inserter还带有第二个实参:指向插入起始位置的迭代器,inserter总是在它的迭代器参数所标明的位置前面插入新元素。
流迭代器
虽然iostream类型不是容器,但标准库同样提供了在iostream对象上使用的迭代 器:istream_iterator用于读取读入流,而ostream_iterator用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素 序列。使用流迭代器时,可以用泛型算法从流对象中读数据(或将数据写到流对象中)。
istream_iterator<T> in(strm); 创建从输入流strm中读取T类型对象的istream_iterator对象,strm是一个输入流
istream_iterator<T> in; istream_iterator对象的超出末端迭代器
ostream_iterator<T> out(strm); 创建将T类型的对象写到输出流strm的ostream_iterator对象
ostream_iterator<T> out(strm, delim); 创建将T类型的对象写到输出流strm的ostream_iterator对象,在写入过程中使用delim作为元素的分隔符。delim是以空字符结束的字符数组
流迭代器只定义了最基本的迭代器操作:自增、引用和赋值。此外,可比较两个istream迭代器是否相等(或不等)。而ostream迭代器则不提供比较运算。
流迭代器的限制:
(1)不可能从ostream_iterator对象读入,也不可能写到istream_iterator对象中;
(2)一旦给ostream_iterator对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator对象中每个不同的值都只能正好输出一次。
(3)ostream_iterator没有->操作符。
测试:
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main() {
istream_iterator<int> in_iter(cin);
istream_iterator<int> eof;
//vector<int> vec(in_iter, eof); //do the same work as following loop
vector<int> vec;
while (in_iter != eof)
vec.push_back(*in_iter++); //*in_iter可以取出输入流中得元素
vector<int>::const_iterator it = vec.begin();
for(; it != vec.end(); ++it)
cout<<*it<<endl;
return 0;
}
#include <iostream>
#include <iterator>
using namespace std;
int main() {
ostream_iterator<string> out_iter(cout, ""n");
istream_iterator<string> in_iter(cin), eof;
while (in_iter != eof)
*out_iter++ = *in_iter++;
return 0;
}
反向迭代器
反向迭代器是一种反向遍历容器的迭代器。也就是,从最后一个元素到第一个元素遍历容器。反向迭代器将自增(和自减)的含义反过来了:对于反向迭代器,++运算将访问前一个元素,而--运算则访问下一个元素。
(1)反向迭代器需要使用自减操作符:标准容器上的迭代器(reverse_iterator)既支持自增运算,也支持自减运算。但是,流迭代器由于不能反向遍历流,因此流迭代器不能创建反向迭代器。
(2)可以通过reverse_iterator::base()将反向迭代器转换为普通迭代器使用,从逆序得到普通次序。
测试:
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;
int main() {
string str = "this 'sentence' is a test";
cout<<str<<endl;
string::iterator it1 = find(str.begin(), str.end(), '"'');
string::iterator it2 = find(++it1, str.end(), '"'');
cout<<string(it1, it2)<<endl;
string::reverse_iterator rit1 = find(str.rbegin(), str.rend(), '"'');
string::reverse_iterator rit2 = find(++rit1, str.rend(), '"'');
cout<<string(rit1, rit2)<<endl;
cout<<string(rit2.base(), rit1.base())<<endl;
getchar();
return 0;
}
不同的迭代器支持不同的操作集,而各种算法也要求相应的迭代器具有最小的操作集。因此,可以将算法的迭代器分为下面五类:
输入迭代器
(input iterator) 读,不能写。支持的操作集:==, !=, 前缀++, 后缀++, *, ->。例如,find, accumulate算法要求这类迭代器。
输出迭代器
(output iterator) 写,不能读。支持的操作集:前缀++, 后缀++, *(只能出现在赋值运算的左操作数上)。推出迭代器要求每个迭代器必须正好写入一次。例如,ostream_iterator是输出迭代器,copy算法使用这类迭代器。
前向迭代器(forward iterator) 读和写,支持输入迭代器和输出迭代器提供的所有操作,还支持对同一个元素的多次读写。例如,replace算法需要这种迭代器。
双向迭代器(bidirectional iterator) 读和写,除了支持前向迭代器的所有操作,还支持前缀--和后缀--,即支持双向遍历容器。例如,reverse算法要求这类迭代器。标准库容器中提供的迭代器都至少达到双向迭代器的要求。
随机访问迭代器(random-access iterator) 读和写。提供在常量时间内访问容器任意位置的功能。支持完整的迭代器操作集:1)关系运算:==, !=, <, <=, >, >=;2)算术运算:it + n, it - n, it += n, it -= n以及it1 - it2;3)下标运算:it[n],等价于*(it + n)。需要随机访问迭代器的泛型算法包括sort算法。例如,vector, deque, string迭代器是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。
除了输出迭代器,其他类别的迭代器形成了一个层次结构:需要低级类别迭代器的地方,可使用任意一种更高级的迭代器。例如,对于需要输入迭代器的算法,可传 递前向、双向或随机访问迭代器调用该算法。而反之则不行。注意:向算法传递无效的迭代器类别所引起的错误,无法保证会在编译时被捕获到。
map, set, list类型提供双向迭代器,而string, vector和deque容器上定义的迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。istream_iterator是输 入迭代器,ostream_iterator是输出迭代器。
另外,虽然map和set类型提供双向迭代器,但关联容器只能使用这部分算法的一个子集。因为关联容器的键是const对象。因此,关联容器不能使用任何 写序列元素的算法。只能使用与关联容器绑在一起的迭代器来提供用于读操作的实参。因此,在处理算法时,最好将关联容器上的迭代器视为支持自减运算的输入迭 代器,而不是完整的双向迭代器。