码迷,mamicode.com
首页 > 编程语言 > 详细

八、C++ 标准模板库-STL概述

时间:2016-07-10 19:12:48      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:

C++ 标准模板库-STL概述

一、基本概念

1.1 泛型程序设计

C++ 语言的核心优势之一就是便于软件的重用,重用在两个方面有体现:

  1. 面向对象的思想:继承和多态,标准类库
  2. 泛型程序设计(generic programming) 的思想: 模板机制,以及标准模板库 STL

简单地说就是使用模板的程序设计法。将一些常用的数据结构(比如链表,数组,二叉树)和算法(比如排序,查找)写成模板,以后则不论数据结构里放的是什么对象,算法针对什么样的对象,则都不必重新实现数据结构,重新编写算法。

标准模板库 (Standard Template Library) 就是一些常用数据结构和算法的模板的集合。有了STL,不必再写大多的标准数据结构和算法,并且可获得非常高的性能。

1.2 STL中基本的概念

容器: 可容纳各种数据类型的通用数据结构,是类模板
迭代器: 可用于依次存取容器中元素,类似于指针
算法: 用来操作容器中的元素的函数模板

二、容器概述

容器指可以用于存放各种类型的数据( 基本类型的变量,对象等)的数据结构,都是类模版,分为三种:

  1. 顺序容器
    vector, deque,list
  2. 关联容器
    set, multiset, map, multimap
  3. 容器适配器
    stack, queue, priority_queue

对象被插入容器中时,被插入的是对象的一个复制品。许多算法,比如排序,查找,要求对容器中的元素进行比较,有的容器本身就是排序的,所以,放入容器的对象所属的类,往往还应该重载 == 和 < 运算符。

2.1 顺序容器

顺序容器并非指容器内的元素是排序的,元素的插入位置同元素的值无关。有vector,deque,list 三种。

vector 指动态数组。元素在内存连续存放。随机存取任何元素都能在常数时间完成,在尾端增删元素具有较佳的性能(大部分情况下是常数时间)。头文件是< vector>
技术分享

deque指双向队列。元素在内存连续存放。随机存取任何元素都能在常数时间完成(但次于vector)。在两端增删元素具有较佳的性能(大部分情况下是常数时间)。
技术分享

list指双向链表。元素在内存不连续存放。在任何位置增删元素都能在常数时间完成。 不支持随机存取。
技术分享

2.2 关联容器

关联容器有以下几个特点:

  1. 元素是排序的
  2. 插入任何元素,都按相应的排序规则来确定其位置
  3. 在查找时具有非常好的性能
  4. 通常以平衡二叉树方式实现, 插入和检索的时间都是 O(log(N))

有两类:

  1. set/multiset(头文件 < set>)
    set 即集合。 set中不允许相同元素, multiset中允许存在相同的元素。

  2. map/multimap(头文件 < map>)
    map与set的不同在于map中存放的元素有且仅有两个成员变量,一个名为first,另一个名为second, map根据first值对元素进行从小到大排序,并可快速地根据first来检索元素。
    map同multimap的不同在于是否允许相同first值的元素

2.3 容器适配器

容器适配器有3类:stack、queue、priority_queue。

stack指栈。是项的有限序列,并满足序列中被删除、检索和修改的项只能是最近插入序列的项(栈顶的项)。 后进先出。头文件是< stack>
技术分享

queue指队列。插入只可以在尾部进行,删除、检索和修改只允许从头部进行。 先进先出。头文件是< queue>。
技术分享

priority_queue指优先级队列。最高优先级元素总是第一个出列。头文件是< queue>。

2.4 成员函数

顺序容器和关联容器中都有的成员函数:

begin 返回指向容器中第一个元素的迭代器
end 返回指向容器中最后一个元素后面的位置的迭代器
rbegin 返回指向容器中最后一个元素的迭代器
rend 返回指向容器中第一个元素前面的位置的迭代器
erase 从容器中删除一个或几个元素
clear 从容器中删除所有元素
front :返回容器中第一个元素的引用
back : 返回容器中最后一个元素的引用
push_back : 在容器末尾增加新元素
pop_back : 删除容器末尾的元素
erase :删除迭代器指向的元素(可能会使该迭代器失效),或删除一个区间,返回被删除元素后面的那个元素的迭代器

三、迭代器

3.1 基本概念

迭代器用于指向顺序容器和关联容器中的元素,用法和指针类似,有const 和非 const两种。通过迭代器可以读取它指向的元素,通过非const迭代器还能修改其指向的元素。

定义一个容器类的迭代器的方法可以是:

容器类名::iterator 变量名;
容器类名::const_iterator 变量名;

访问一个迭代器指向的元素:

* 迭代器变量名

迭代器上可以执行 ++ 操作, 以使其指向容器中的下一个元素。如果迭代器到达了容器中的最后一个元素的后面,此时再使用它,就会出错,类似于使用NULL或未初始化的指针一样。

3.2 迭代器示例

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> v; //一个存放int元素的数组,一开始里面没有元素
    v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);

    vector<int>::const_iterator i; //常量迭代器
    for( i = v.begin();i != v.end();++i )
        cout << * i << ",";
    cout << endl;

    vector<int>::reverse_iterator r; //反向迭代器
    for( r = v.rbegin();r != v.rend();r++ )
        cout << * r << ",";
    cout << endl;

    vector<int>::iterator j; //非常量迭代器
    for( j = v.begin();j != v.end();j ++ )
        * j = 100;
    for( i = v.begin();i != v.end();i++ )
        cout << * i << ",";
}

输出:

1,2,3,4,
4,3,2,1,
100,100,100,100,

3.3 迭代器类别

3.3.1 双向迭代器

若p和p1都是双向迭代器,则可对p、 p1可进行以下操作:

++p, p++ 使p指向容器中下一个元素
--p, p-- 使p指向容器中上一个元素
* p 取p指向的元素
p = p1 赋值
p == p1 , p!= p1 判断是否相等、不等

3.3.2 随机访问迭代器

若p和p1都是随机访问迭代器,则可对p、 p1可进行以下操作:

双向迭代器的所有操作
p += i 将p向后移动i个元素
p -= i 将p向向前移动i个元素
p + i 值为: 指向 p 后面的第i个元素的迭代器
p - i 值为: 指向 p 前面的第i个元素的迭代器
p[i] 值为: p后面的第i个元素的引用
p < p1, p <= p1, p > p1, p>= p1

3.3.3 容器和迭代器

容器 容器对应的迭代器
vector 随机访问
deque 随机访问
list 双向
set/multiset 双向
map/multimap 双向
stack 不支持迭代器
queue 不支持迭代器
priotiry_queue 不支持迭代器

四、算法简介

4.1 基本概念

算法就是一个个函数模板, 大多数在< algorithm> 中定义。

STL中提供能在各种容器中通用的算法,比如查找,排序等算法通过迭代器来操纵容器中的元素。许多算法可以对容器中的一个局部区间进行操作,因此需要两个参数,一个是起始元素的迭代器,一个是终止元素的后面一个元素的迭代器。比如,排序和查找。有的算法返回一个迭代器。比如 find() 算法,在容器中查找一个元素,并返回一个指向该元素的迭代器。

算法可以处理容器,也可以处理普通数组。

4.2 算法示例

template<class InIt, class T>
InIt find(InIt first, InIt last, const T& val);

first 和 last 这两个参数都是容器的迭代器,它们给出了容器中的查找区间起点和终点[first,last)。区间的起点是位于查找范围之中的,而终点不是。 find在[first,last)查找等于val的元素用 == 运算符判断相等。

函数返回值是一个迭代器。如果找到,则该迭代器指向被找到的元素。如果找不到,则该迭代器等于last。

五、STL中“大”、“小”、“相等”的概念

5.1 基本概念

关联容器内部的元素是从小到大排序的

  1. 有些算法要求其操作的区间是从小到大排序的,称为“ 有序区间算法”
    例: binary_search
  2. 有些算法会对区间进行从小到大排序,称为“排序算法”
    例: sort
  3. 还有一些其他算法会用到“大”,“小”的概念

使用STL时,在缺省的情况下,以下三个说法等价:

  1. x比y小
  2. 表达式“ x < y”为真
  3. y比x大

关于“相等”:

  1. 有时,“ x和y相等”等价于“ x==y为真”
    例:在未排序的区间上进行的算法,如顺序查找find
    ……
  2. 有时“ x和y相等”等价于“ x小于y和y小于x同时为假”
    例:
    有序区间算法,如binary_search
    关联容器自身的成员函数find
    ……

5.2 程序示例

#include<vector>
#include<algorithm>
using namespace std;

class A
{
    int v;
    public:
        A(int v):v(v) { }
        bool operator<(const A &a) const{
            cout<<v<<"<"<<a.v<<"?"<<endl;
            return false;
        }
        bool operator==(const A &a) const{
            cout<<v<<"=="<<a.v<<"?"<<endl;
            return v==a.v;
        }
};

int main()
{
    //重载运算符 < 后的二分查找 
    A a[] = {A(1), A(2), A(3), A(4), A(5)};
    cout<<binary_search(a, a+5, A(9));

    return 0;
}

输出:

3<9?
2<9?
1<9?
9<1?
1

折半查找,最后找到1没有更多的可以找了。比较9是否小于1,结果为假;比较1是否小于9,结果为假;这时候认为9==1,输出1。

六、小结

  1. STL 三个基本概念:容器、迭代器、算法
  2. 容器分为顺序容器、关联容器、容器适配器
  3. 顺序容器分为vector(动态数组)、deque(双向队列)、list(双向链表)
  4. 关联容器分为set/multiset、map/multimap
  5. 容器适配器stack、queue、priority_queue
  6. 迭代器分为双向迭代器、随机访问迭代器,不同的容器可以使用的迭代器类别不同
  7. 算法就是一个个函数模板, 大多数在< algorithm> 中定义
  8. STL 中的”大“、”小“、”相等“等概念可以自己定义,可能和常规意义上的概念不同

八、C++ 标准模板库-STL概述

标签:

原文地址:http://blog.csdn.net/u011330638/article/details/51861982

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!