C++——标准模板库

1、泛型程序设计:将程序尽可能写的通用,将算法从特定的数据结构中抽象出来,成为通用的;C++模板为泛型程序设计奠定了关键的基础;STL是泛型程序设计的一个范例:容器container、迭代器iterator、算法algorithms和函数对象function object。

2、命名空间namespace:一个命名空间将不同的标识符集合在一个命名作用域(named scope)中,是为了解决命名冲突。没有声明命名空间的标识符都处在无名的命名空间中。

例如,声明一个命名空间NS:
namspace NS {
class File;
void Fun ();
}
则引用标识符的方式如下,
NS:: File obj;
NS:: Fun ();

可以利用using namespace std;指定在命名空间std中所有标识符都可以直接饮用,using NS::file;在当前作用域中就可以直接饮用file。

在新的C++标准程序库中,所有标识符都声明在命名空间std中,头文件都不使用扩展名。

3、容器:容器类是容纳、包含一组元素或元素集合的对象。异类容器类与同类容器类。还可以分为顺序容器与关联容器。七种基本容器:向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)

容器的接口:外界可以使用的功能。包括方法函数和运算符。

通用运算符:==,!=,>,>=,<,<=,=
迭代方法begin(),end(),rbegin(),rend();访问方法size(),max_size(),swap(),empty()

顺序容器:接口:插入方法 push_front(), push_back(), insert(), 运算符"="。

                 删除方法 pop(), erase(),clear()

                 迭代访问方法 使用迭代器

                 其他顺序容器访问方法(不修改的访问方法) front(),back(),下标运算符[]。

顺序容器向量:向量属于顺序容器,用于容纳不定长的线性序列,提供对序列的快速随机访问,就是直接访问。向量是动态结构,它的大小不固定,可以在程序运行时增加或者减少。

例子:求反问2~N中的质数,N在程序运行时由键盘输入。

#include <iostream>
#include <iomanip>
#include <vector> //包含向量容器头文件
using namespace std ;
int main()
{   
    vector<int>  A(10); // 用来存放质数的向量,初始状态有10个元素。
    int n; //质数范围的上限,运行时输入
    int primecount = 0, i, j;
    cout << "Enter a value >= 2 as upper limit for prime numbers: ";
    cin >> n;
    A[primecount++] = 2; // 2是一个质数
    for(i = 3; i < n; i++)
    {
        if (primecount == A.size()) // 如果质数表已满,则再申请10个元素的空间
            A.resize(primecount + 10);
        if (i % 2 == 0) //大于2的偶数不是质数,因此略过本次循环的后继部分
            continue;
        // 检查3,5,7,...,i/2是否i的因子
        j = 3;
        while (j <= i/2 && i % j != 0)
            j += 2;       

        if (j > i/2) // 若上述参数均不为i的因子,则i为质数
            A[primecount++] = i;
    }
    for (i = 0; i < primecount; i++) //输出质数
    {
        cout << setw(5) << A[i];
        if ((i+1) % 10 == 0) //每输出10个数换行一次
            cout << endl;
    }
    cout << endl;
}

4、适配器:适配器是一种接口类,为已有的类提供新的接口,目的是简化、约束,使之安全、隐藏或者改变被修改类提供的服务的集合。主要有三种适配器类型:容器适配器(用来扩展7中基本容器),迭代器适配器和函数对象适配器。

5、迭代器:是面向对象版本的指针,提供了访问容器、序列中每个元素的方法

输入迭代器
可以用来从序列中读取数据
输出迭代器
允许向序列中写入数据
前向迭代器
既是输入迭代器又是输出迭代器,并且可以对序列进行单向的遍历
双向迭代器
与前向迭代器相似,但是在两个方向上都可以对数据遍历
随机访问迭代器
也是双向迭代器,但能够在序列中的任意两个位置之间进行跳转。
6、算法:标准模板库中包括了70多个算法,其中包括了查找算法、排序算法、消除算法、计数算法、比较算法、变换算法、置换算法和容器管理等等

算法是一种函数模板,可以分为

不可变序列算法(non-mutating algorithms),不直接修改所操作的容器内容的算法
可变序列算法(mutating algorithms),可以修改它们所操作的容器的元素。
排序相关算法和数值算法
例6-1,应用不可变序列算法对数据序列进行分析
例6-2,以可变序列算法对数据序列进行复制,生成,删除,替换,倒序,旋转等可变性操作。
例6-3,应用排序相关算法对序列进行各项操作
例6-4,应用数值算法对数据序列进行操作

//6-1.cpp
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

int main()
{
 int iarray[]={0,1,2,3,4,5,6,6,6,7,8};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));
 int iarray1[]={6,6};
 vector<int> ivector1(iarray1,iarray1+sizeof(iarray1)/sizeof(int));  
 int iarray2[]={5,6};
 vector<int> ivector2(iarray2,iarray2+sizeof(iarray2)/sizeof(int));
 int iarray3[]={0,1,2,3,4,5,7,7,7,9,7};
 vector<int> ivector3(iarray3,iarray3+sizeof(iarray3)/sizeof(int));

 //找出ivector之中相邻元素值相等的第一个元素
 cout<<*adjacent_find(ivector.begin(),ivector.end())<<endl;

 //找出ivector之中元素值为6的元素个数
 cout<<count(ivector.begin(),ivector.end(),6)<<endl;

 //找出ivector之中小于7的元素个数
 cout<<count_if(ivector.begin(),ivector.end(),bind2nd(less<int>(),7))<<endl;

 //找出ivector之中元素值为4的第一个元素所在位置的元素
 cout<<*find(ivector.begin(),ivector.end(),4)<<endl;

 //找出ivector之中大于2的第一个元素所在位置的元素
 cout<<*find_if(ivector.begin(),ivector.end(),bind2nd(greater<int>(),2))
<<endl;
 
 //找出ivector之中子序列ivector1所出现的最后一个位置,再往后3个位置的元素
 cout<<*(find_end(ivector.begin(),ivector.end(),ivector1.begin(),
ivector1.end())+3)<<endl;

 //找出ivector之中子序列ivector1所出现的第一个位置,再往后3个位置的元素
 cout<<*(find_first_of(ivector.begin(),ivector.end(),ivector1.begin(),
ivector1.end())+3)<<endl;
 
 //子序列ivector2在ivector中出现的起点位置元素
 cout<<*search(ivector.begin(),ivector.end(),ivector2.begin(),ivector2.end())
<<endl;

 //查找连续出现3个6的起点位置元素
 cout<<*search_n(ivector.begin(),ivector.end(),3,6,equal_to<int>())<<endl;

 //判断两个区间ivector和ivector3相等否(0为假,1为真)
cout << equal(ivector.begin(), ivector.end(), ivector3.begin()) << endl;

 //查找区间ivector3在ivector中不匹配点的位置
pair<int*,int*>result=mismatch(ivector.begin(),ivector.end(),ivector3.begin());
cout<< result.first - ivector.begin() << endl;
}
//6-2.cpp
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

class even_by_two{             //类定义形式的函数对象
public:
 int operator()() const
 {return _x+=2;}
private:
 static int _x;
};
int even_by_two::_x=0;       //静态数据成员初始化

int main()
{
 int iarray[]={0,1,2,3,4,5,6,6,6,7,8};
 int iarray1[]={0,1,2,3,4,4,5,5,6,6,6,6,6,7,8};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));
 vector<int> ivector1(iarray+6,iarray+8);  
 vector<int> ivector2(iarray1,iarray1+sizeof(iarray1)/sizeof(int));
 ostream_iterator< int > output( cout, " " );  //定义流迭代器用于输出数据
 
 //迭代遍历ivector1区间,对每一个元素进行even_by_two操作
    generate(ivector1.begin(),ivector1.end(),even_by_two());
 copy(ivector1.begin(),ivector1.end(),output);
 cout<<endl;

 //迭代遍历ivector的指定区间(起点和长度),对每一个元素进行even_by_two操作
    generate_n(ivector.begin(),3,even_by_two());
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;

 //删除元素6
    remove(ivector.begin(),ivector.end(),6);
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //删除(实际并未从原序列中删除)元素6,结果置于另一个区间
    vector<int> ivector3(12);
 remove_copy(ivector.begin(),ivector.end(),ivector3.begin(),6);
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;

 //删除(实际并未从原序列中删除)小于6的元素
 remove_if(ivector.begin(),ivector.end(),bind2nd(less<int>(),6));
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //删除(实际并未从原序列中删除)小于7的元素,结果置于另一个区间,
 remove_copy_if(ivector.begin(),ivector.end(),ivector3.begin(),
bind2nd(less<int>(),7));
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //将所有的元素值6,改为元素值3
 replace(ivector.begin(),ivector.end(),6,3);
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //将所有的元素值3,改为元素值5,结果放置到另一个区间
 replace_copy(ivector.begin(),ivector.end(),ivector3.begin(),3,5);
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //将所有小于5的元素值,改为元素值2
 replace_if(ivector.begin(),ivector.end(),bind2nd(less<int>(),5),2);
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //将所有的元素值8,改为元素值9,结果放置到另一个区间
 replace_copy_if(ivector.begin(),ivector.end(),ivector3.begin(),
bind2nd(equal_to<int>(),8),9);
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //逆向重排每一个元素
 reverse(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //逆向重排每一个元素,结果置于另一个区间
 reverse_copy(ivector.begin(),ivector.end(),ivector3.begin());
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
 
 //旋转(互换元素)[first,middle), 和[middle,end)
 rotate(ivector.begin(),ivector.begin()+4,ivector.end());
 copy(ivector.begin(),ivector.end(),output);
 cout<<endl;
 
 //旋转(互换元素)[first,middle], 和[middle,end],结果置于另一个区间,
 rotate_copy(ivector.begin(),ivector.begin()+5,ivector.end(),
ivector3.begin());
 copy(ivector3.begin(),ivector3.end(),output);
 cout<<endl;
}

//6-3.cpp
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;

int main()
{
 int iarray[]={26,17,15,22,23,33,32,40};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));
 
 // 查找并输出最大、最小值元素
 cout<<*max_element(ivector.begin(),ivector.end())<<endl;
 cout<<*min_element(ivector.begin(),ivector.end())<<endl;

 //将ivector.begin()+4-ivector.begin()各元素排序,
 //放进[ivector.begin(),ivector.begin()+4]区间。剩余元素不保证维持原来相对次序
 partial_sort(ivector.begin(),ivector.begin()+3,ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //局部排序并复制到别处
 vector<int> ivector1(5);
 partial_sort_copy(ivector.begin(),ivector.end(),ivector1.begin(),
ivector1.end());
 copy(ivector1.begin(),ivector1.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //排序,缺省为递增。
 sort(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //将指定元素插入到区间内不影响区间原来排序的最低、最高位置
 cout<<*lower_bound(ivector.begin(),ivector.end(),24)<<endl;
 cout<<*upper_bound(ivector.begin(),ivector.end(),24)<<endl;

 //对于有序区间,可以用二分查找方法寻找某个元素
    cout<<binary_search(ivector.begin(),ivector.end(),33)<<endl;
    cout<<binary_search(ivector.begin(),ivector.end(),34)<<endl;

 //下一个排列组合
 next_permutation(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //上一个排列组合
 prev_permutation(ivector.begin(),ivector.end());
 copy(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //合并两个序列ivector和ivector1,并将结果放到ivector2中
 vector<int> ivector2(13);
 merge(ivector.begin(),ivector.end(),ivector1.begin(),ivector1.end(),
ivector2.begin());
 copy(ivector2.begin(),ivector2.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //将小于*(ivector.begin()+5)的元素放置在该元素之左
 //其余置于该元素之右。不保证维持原有的相对位置
 nth_element(ivector2.begin(),ivector2.begin()+5,ivector2.end());
 copy(ivector2.begin(),ivector2.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //排序,并保持原来相对位置
 stable_sort(ivector2.begin(),ivector2.end());
 copy(ivector2.begin(),ivector2.end(),ostream_iterator<int>(cout," "));
 cout<<endl;

 //针对一个有序区间,找出其中一个子区间,其中每个元素都与某特定元素值相同
 pair<vector<int>::iterator,vector<int>::iterator> pairIte;
 pairIte=equal_range(ivector2.begin(),ivector2.end(),22);
 cout<<*(pairIte.first)<<endl;
 cout<<*(pairIte.second)<<endl;

 //合并两个有序序列,然后就地替换
 int iarray3[] = { 1, 3, 5, 7, 2, 4, 6, 8 };
 vector<int> ivector3(iarray3,iarray3+sizeof(iarray3)/sizeof(int));
 inplace_merge(ivector3.begin(), ivector3.begin()+ 4, ivector3.end());
 copy(ivector3.begin(),ivector3.end(), ostream_iterator<int>(cout, " ")); 
 cout<<endl;
 
 //以字典顺序比较序列ivector3和ivector4
 int iarray4[] = { 1, 3, 5, 7,1, 5, 9, 3 };
 vector<int> ivector4(iarray4,iarray4+sizeof(iarray4)/sizeof(int));
 cout<< lexicographical_compare(ivector3.begin(),ivector3.end(),
ivector4.begin(),ivector4.end()) << endl;
}
//6-4.cpp
#include <iostream>
#include <numeric>
#include <functional>
#include <vector>
using namespace std;

int main()
{
 int iarray[]={1,2,3,4,5};
 vector<int> ivector(iarray,iarray+sizeof(iarray)/sizeof(int));

 //元素的累计
 cout<<accumulate(ivector.begin(),ivector.end(),0)<<endl;
 //向量的内积
 cout<<inner_product(ivector.begin(),ivector.end(),ivector.begin(),10)<<endl;
 //向量容器中元素局部求和
 partial_sum(ivector.begin(),ivector.end(),ostream_iterator<int>(cout," "));
 cout<<endl;
 //向量容器中相邻元素的差值
 adjacent_difference(ivector.begin(),ivector.end(),
ostream_iterator<int>(cout," "));
 cout<<endl;
}
7、函数对象:一个行为类似于函数的对象,它可以没有参数,也可以带有若干参数,其功能是获取一个值,或者改变操作的状态。任何普通的函数和任何重载了调用运算符operate()的类的对象都满足函数对象的特征,STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。

posted @ 2019-01-08 11:35  lemaden  阅读(369)  评论(0编辑  收藏  举报