C++ STL — 第5章 The STL(一)

来源:互联网 发布:java实战案例 编辑:程序博客网 时间:2024/05/13 06:21

STL :基于各种结构良好的组件,核心的有:containers、iterators、algorithms

container:容器,用来存放和管理某种具体的对象,每种容器都有自己的特点,使用时候按需采用

iterator:迭代器,用来遍历容器内的元素,这种接口可以独立于某个容器而不关心内部实现,对外提供统一的访问接口,例如向后移动++,取得元素*,其行为类似于指针但比指针安全多了。

algorithm:算法,处理容器内的元素,例如查找、排序、修改等等。算法使用iterator,因此一个算法可以适用于大部分容器,因为基本都提供了相同的iterator接口


STL建立在数据和操作分离的基础上,容器管理数据,算法是操作,迭代器是中间的桥梁。



为了适应不同的需求,STL提供了不同种类的容器:


两种类型:

顺序容器sequence: vector,deque,list,元素有序且有个特定的位置,与插入的时间和位置有关

关联容器associative: set,multiset,map,multimap,根据值内部自动排好序,与插入无关,仅仅取决于值


vector:动态数组

可以通过下标随机存储

尾部增加、删除元素非常快 - 常量,中间或前面插入元素较慢 - 线性

#include <iostream>#include <vector>using namespace std; int main(){    vector<int> coll;    for(int i=1; i<=6; i++)    {        coll.push_back(i);    }     for(int i=0; i<coll.size(); i++)    {        cout << coll[i] << " ";    }    cout << endl;    return 0;}/* * 1 2 3 4 5 6 */

vector<int> coll; //创建空容器没有任何元素

push_back();  //顺序容器都有的函数,尾部添加元素

size(); //返回元素的元素个数

[];操作符取得容器内元素 


deque:double-ended queue,动态数组,两端都可以动态增长,首尾插入元素都很快

#include <iostream>#include <deque>using namespace std; int main(){    deque<float> coll;    for(int i=1; i<=6; i++)    {        coll.push_front(i * 1.1);    }     for(int i=0; i<coll.size(); i++)    {        cout << coll[i] << " ";    }    cout << endl;    return 0;}/* * 6.6 5.5 4.4 3.3 2.2 1.1 */

list:双向链表,不提供随机存储,但是在中间插入和删除元素非常快,每个链表元素都有个前驱和后继

#include <iostream>#include <list> using namespace std; int main(){    list<char> coll;    for(char c='a'; c<='z'; c++)    {        coll.push_back(c);    }     while(!coll.empty())    {        cout << coll.front() << " ";        coll.pop_front();    }    cout << endl;    return 0;}//a b c d e f g h i j k l m n o p q r s t u v w x y z

string:类似于vector<char>

包括basic_string<>,string, wstring三个


普通数组:可以调用STL中的algorithm


associative container: < 默认比较,二叉树实现,模板参数

set:根据值排序好的集合,每个元素仅仅出现一次,不允许副本

multiset:允许副本的set,也就是相同的值出现

map:包含键值对key/value元素的容器,key 是基于一定标准的排序而且仅仅出现一次

multimap:允许出现相同的key


容器适配器:adapter,以基础容器为蓝本实现的

栈stack:后进先出

队列queue:先进先出

priority_queue:优先级队列


iterator迭代器:代表容器中的某个位置

operator*:取得对象值,如果对象有members,还可以直接用->直接调用取得。

operator++:++移至下一个元素,--向前推一个元素

operator==:==两个迭代器指向同一个位置,!=则相反

operator=:赋值(iter指向的元素的位置的赋值)


所有的容器都提供的方法支持迭代器:

begin():容器的首个元素

end():容器的超出末端,最后一个元素的下一个位置

#include <list>using namespace std; int main(){    list<char> coll;    for(char c='a'; c<='z'; c++)    {        coll.push_back(c);    }     list<char>::const_iterator pos;    for(pos = coll.begin(); pos != coll.end(); pos++)    {        cout << *pos << " ";    }    cout << endl;    return 0;}//a b c d e f g h i j k l m n o p q r s t u v w x y z

每种容器都定义了两种迭代器:

container::iterator  :   读写

container::const_iterator : 只读

list<char>iterator iter;for(iter=coll.begin();iter!=coll.end();iter++){    *iter = toupper(*iter);}

注意:++pos比 pos++更快


set 使用iterator:

#include <iostream>#include <set>using namespace std; int main(){    typedef set<int> IntSet;    IntSet coll;    coll.insert(3);    coll.insert(1);    coll.insert(5);    coll.insert(4);    coll.insert(1);    coll.insert(6);    coll.insert(2);     IntSet::const_iterator pos;    for(pos=coll.begin(); pos!=coll.end(); ++pos)    {        cout << *pos << " ";    }    cout << endl;    return 0;}//1 2 3 4 5 6

如果希望排序规则按照从大到小:typedef set<int, greater<int> > IntSet;

greater是一个函数对象

所有的关联容器都提供了一个insert()函数

#include <iostream>#include <map>using namespace std; int main(){    //typedef set<int> IntSet;    typedef multimap<int, string> IntString;    IntString coll;    coll.insert(make_pair(5,"tagged"));    coll.insert(make_pair(2,"a"));    coll.insert(make_pair(1,"this"));    coll.insert(make_pair(4,"of"));    coll.insert(make_pair(6,"strings"));    coll.insert(make_pair(1,"is"));    coll.insert(make_pair(3,"multimap"));     IntString::const_iterator pos;    for(pos=coll.begin(); pos!=coll.end(); ++pos)    {        //cout << pos->second << " ";        cout << (*pos).second << " ";    }    cout << endl;    return 0;}//this is a multimap of tagged strings

如果是map,还可以这样赋值给map,类似于一个关联数组:map<int, string> coll;

1
2
3
4
5
6
7
coll[5] = "tagged";
coll[2] = "a";
coll[0] = "this";
coll[4] = "of";
coll[6] = "strings";
coll[1] = "is";
coll[3] = "multimap";

迭代器分类:

bidirectional,双向的:list,set,multiset,map,multimap

random access,随机存储:也是双向的而且有< 和 >:vector,deque,string


算法:搜索、排序、拷贝、重新排序、修改、数值运算

以迭代器为基础的全局函数

泛型函数式编程思维模式 - 接口,算法可以操作不同的容器,只要有相同的接口,即迭代器

#include <iostream>#include <algorithm>#include <vector>using namespace std;int main(){    vector<int> coll;    vector<int>::iterator pos;     coll.push_back(2);    coll.push_back(5);    coll.push_back(4);    coll.push_back(1);    coll.push_back(6);    coll.push_back(3);     pos = min_element(coll.begin(), coll.end());    cout << "min : " << *pos << endl; //1    pos = max_element(coll.begin(), coll.end());    cout << "max : " << *pos << endl; //6     sort(coll.begin(), coll.end());    pos = find(coll.begin(), coll.end(), 3);    reverse(pos, coll.end());     for(pos=coll.begin(); pos!=coll.end(); ++pos)    {        cout << *pos << " ";    }    cout << endl;    return 0;}//1 2 6 5 4 3

区间:range

算法处理的都是半开区间,[begin, end)

注意:只有随机迭代器可以的运算不能用在别的不支持随机迭代器的容器上,尽量使用迭代器通用的操作。

区间的begin一定是在end左边,也就是说begin++最终是能到达end的

多个区间,通常第二个区间的元素个数是根据第一个区间推导得知

#include <iostream>#include <vector>#include <list>using namespace std;int main(){    vector<int> coll1;    list<int> coll2;    for(int i=1; i<=9; i++)    {        coll1.push_back(i);    }    //确认目标区间内有足够的元素空间    coll2.resize(coll1.size());     copy(coll1.begin(), coll1.end(), coll2.begin());    for(list<int>::iterator iter=coll2.begin(); iter!=coll2.end(); ++iter)    {        cout << *iter << " ";    }    cout << endl;    return 0;}//1 2 3 4 5 6 7 8 9

迭代器适配器:

1. 插入迭代器:insert iterator

2. 流迭代器:stream iterator

3. 逆向迭代器:reverse iterator


插入迭代器:

使得算法以安插方式而非覆写的方式运作。解决算法目标空间不足的问题。

#include <iostream>#include <vector>#include <list>#include <algorithm>#include <iterator>#include <deque>#include <set>using namespace std;int main(){    list<int> coll1;    vector<int> coll2;    deque<int> coll3;    set<int> coll4;     for(int i=1; i<=9; i++)    {        coll1.push_back(i);    }     copy(coll1.begin(), coll1.end(), back_inserter(coll2));    copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));    //1 2 3 4 5 6 7 8 9     cout << endl;     copy(coll1.begin(), coll1.end(), front_inserter(coll3));    copy(coll3.begin(), coll3.end(), ostream_iterator<int>(cout, " "));    //9 8 7 6 5 4 3 2 1     cout << endl;     copy(coll1.begin(), coll1.end(), inserter(coll4, coll4.begin()));    copy(coll4.begin(), coll4.end(), ostream_iterator<int>(cout, " "));    //1 2 3 4 5 6 7 8 9    return 0;}

back_inserter(container):安插于尾部迭代器,只有提供了push_back()成员函数才能使用此迭代器,vector, deque, list

front_inserter(container):前端插入迭代器,push_front()函数,deque,list

inserter(container, pos):一般插入迭代器,在pos位置插入元素


流迭代器:stream iterator

#include <iostream>#include <algorithm>#include <vector>#include <iterator>#include <string> using namespace std;int main(){    vector<string> col;    //从cin读入string到col,直到EOF    copy(istream_iterator<string>(cin), istream_iterator<string>(),            back_inserter(col));    //排序    sort(col.begin(), col.end());     //输出到cout,并且无重复    unique_copy(col.begin(), col.end(),            ostream_iterator<string>(cout,"\n"));    return 0;}

逆向迭代器:reverse iterator

将递增运算转换为递减运算

所有容器都可以透过函数rbegin(), rend()产生reverse iterator

#include <iostream>#include <algorithm>#include <vector>#include <iterator> using namespace std;int main(){    vector<int> coll;    for(int i=1; i<=9; ++i)    {        coll.push_back(i);    }    copy(coll.rbegin(), coll.rend(), ostream_iterator<int>(cout," "));    cout << endl;    return 0;}//9 8 7 6 5 4 3 2 1