PoEdu - C++阶段班 【Po学校】- STL专题 (一) 从整体上把握stl上的概念 笔记整理

STL (一) 从整体上把握stl上的概念

  • 泛型程序设计

    • 泛型编程(generic programming):也称为通用编程,类属编程
    • 目标是: 将程序写得尽可能通用.
    • 将算法从数据结构中抽象出来,成为通用的.
      • 算法是对数据处理的逻辑,不同的数据结构,可能都有相同数据逻辑
      • 泛型的目的就是: 用相同的逻辑来对不同的数据结构,不同的数据类型来进行操作.
        • 比如"冒泡"(Sort),用它来对不同的类型排序: 数组,链表,树. 而不是对每一种单独的数据,来做单独的排序算法.
      • 泛型需要把类型来当作参数传递.
    • 泛型就是把类型给"参数化",C++的模板就是这一技术的基石.
  • 什么是STL

    • STL是一个高效的C++程序库. (Standard Template Library),即:标准模板库.
    • STL为C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可利用性.STL中包含了诸多在计算机科学领域里常用的基本数据结构和基本算法.
      • STL的可扩展性:我们可以在STL提供的框架之下 ,扩展出很多新的算法, 它能够适应现有的容器,或数据结构,那么这个新算法,就能对现有的所有数据结构进行操作.
    • 从逻辑层次来看,在STL中体现了泛型化程序设计的思想(generic programming)
      • 这种思想中,大部分基本算法被抽象,被泛化,独立于与之对应的数据结构,用于以相同或相近的方式处理各种不同情形.
    • 从实现层次看,整个STL是以一种参数化(type parameterized)的方式来实现的.
      • 基于模板(template)
      • 有模板的不调用不实例化的特性
      • 泛型把一种类型当参数传递,其实例化时,生成各种不同的类型
      • STL是泛型程序设计思想比较成功的一套产品
  • STL六大组件及其关系

    • 容器(Container) 各种基本数据结构
      • 有人一听说STL就想起来的组件,它是STL中最常用的组件,把STL等同于容器是片面的.
      • 什么是容器: 比如: 数组 动态链表 集合 树 ; 等等,数据结构都是容器.
    • 适配器(Adapter) 可改变containers Iterators 或Function object接口的一种组件
      • 比如用deque vector list 来实现一个Stack,这个自定义的Stack里面有Push,Pop等方法.那么这个自定义的Stack就是一种容器适配器,里面的Push实际上是vector里面的push_back,只因为Stack是先进后出的.再如Pop的实现,就是借助了vector里的接口(方法)pop_back来实现; 如果我们换为实现队列呢,那么Pop的实现,就要借助pop_front这个接口来实现了,因为队列是先进先出的.
      • 如果用其它的如迭代器或函数对象实现的适配器,那就称为迭代器适配器,或函数对象适配器.
    • 算法(Algorithm) 各种基本算法如: sort search......
      • 算法要操作各种数据结构,需要迭代器作为桥梁.
    • 迭代器(Iterator) 连接容器和算法
      • 迭代器是一种智能指针,如胶水连接容器和算法
    • 函数对象(Function object)
      • 以类模板的形式提供的,函数对象它使得类使用起来象一个函数.
      • 一般这些类都要重载括号"()",才能使得类使用起来象是一个函数.
    • 分配器(Allocator)
      • 内存分配器,它提供了容器内部数据的内存分配方式.
        • 这个内存分配方式,可以实现为内存池.
        • 如: SGI STL当中的分配方式,是二级的内存池.
        • VC当中的分配方式,它不是以内存池的方式来实现的.
        • 不同版本的STL,其内存的分配方式是有差异的.是不一样的.但它们都有一致的接口.
  • 容器 算法 迭代器 关系图

    •  
    • 容器为各种基本数据提供支持
    • 算法独立于数据结构,独立于容器,它是一系列逻辑,它能操作各种数据结构
    • 算法操作各种容器或数据结构时,有一个问题:数据结构各种各样,算法怎么就能操作数据结构呢,让算法逻辑得以运行?算法要操纵数据结构,就得遍历数据结构中的所有数据,但各个数据结构是不一样的,算法就不能做出各个数据结构的遍历逻辑,这就需要一种中间"胶水"----迭代器,各种容器都有统一了接口的迭代器,迭代器在各个容器内部都有,迭代器知道容器内部数据结构和数据的分布.那么,算法要操作各个容器和数据结构,就少不了迭代器这个桥梁.
    • 算法不关心如何遍历容器与数据结构,这些遍历交给迭代器来完成.
    • 迭代器来遍历容器,那么它又是如何知道容器内的数据结构的呢? 不同的容器有不同的数据结构,也就意味着需要不同的遍历方式,这个在于 : 每一种容器都提供自己的迭代器.
    • 各种容器各自的迭代器,在外部的角度来看,各种容器都提供了一致的接口:如 ++ 向前遍历 -- 向后遍历 *号取出遍历到的元素,等,具有一致的接口.这些遍历的算法由容器自己去实现.
  • 容器

    • 容器类是容纳,包含一组元素或元素集合的对象
    • 七种基本容器:
      • 1 vector 向量
        • 动态数组,连续有序的
        • 内部空间连续
        •  

           

      • 2 deque 双端队列
        • 动态数组,一片片有序的,数据在每一片空间内是连续的
        • 可以在两个端口进行操作:
        •  

      • 3 list 链表
        • 双向链表,两头都可以操作
        •  

      • 4 set 集合
        • 集合当中关键码key不能重复
        •  

      • 5 multiset 多重集合
        • 多重集合中关键码key能够重复
      • 6 map 映射
        • 除了关键码Key之外,还有值value: Key Value
        • map当中Key是不能重复的
        •  

      • 7 multimap 多重映射
        • 多重映射当中key是可以重复的
    • 七种容器的分类:
      • 序列式容器
        • 每个元素均有固定位置----取决于插入时机和地点,和元素无关.
        • 包括: vector deque list
      • 关联式容器
        • 元素的位置取决于特定的排序准则以及元素值,和插入的次序无关.
        • 包括: set multiset map multimap
  • 如何选择序列式容器

    • vector在尾部插入与删除效率高,但在头部与中间插入删除效率较低.
    • deque在头部与尾部插入与删除效率较高.
      • 下标中间的访问速度也是比较快的,访问效率是常数级别的,不亚于它的空间大小O(n).
      • deque下标访问的算法复杂度是常数级的O(1).
    • list 插入和删除效率高,如需要频繁在序列中间位置上进行插入或删除操作,而且不需要过多的在序列内部进行长距离跳转,应该选择list
  • 迭代器

    • Iterators(迭代器),是容器与算法的桥梁,用来在一个对象群集的元素上进行遍历.这个对象群集或许是一个容器,或许是容器的一部分.迭代器的主要好处是,为所有容器提供了一组很小的公共接口.迭代器以++进行累进,以*进行提领,因而它类似于指针,我们可以把它视为一种smart pointer
    • ++操作可以遍历到群集内的下一个元素.至于如何做到,取决于容器内部的数据组织形式.
    • 每种容器都提供了自己的迭代器,而这些迭代器能够了解容器内部的数据结构.
  • 算法

    • 算法 Algorithms, 用来自责群集内的元素.它们可以出于不同的目的而搜寻、排序、修改、使用那些元素。通过迭代器的协助,我们可以只需要编写一次算法,就可以将它应用于任意容器,这是因为所有的容器迭代器都有提供一致的接口。
  • 适配器

    • 适配器是一种接口类
      • 为已有的接口提供新的接口
      • 目的是简化、约束、使之安全、隐藏或者改变被修改类提供的服务集合。
    • 三种类型的适配器:
      • 1 容器适配器:用来扩展7种基本容器,它们和顺序容器相结合构成栈、队列和优先队列容器
      • 2 迭代器适配器(反向迭代器、插入迭代器、IO流迭代器)
      • 3 函数适配器(函数对象适配器、成员函数适配器、普通函数适配器)

posted on 2017-03-12 00:42  zzdoit  阅读(170)  评论(0)    收藏  举报

导航