泛型程序设计

C++ 的特点

​ C++ 的核心优势之一就是便于软件重用,而软件的重用在 C++ 中主要体现在以下两个方面:

  • 面向对象的思想:继承、多态和标准类库
  • 泛型程序设计的思想:模板机制和标准模板库 STL

泛型程序设计

​ 泛型程序设计通俗地讲就是使用模板的程序设计方法。泛型程序设计中将一些常用的数据结构(例如链表、数组和二叉树等)和算法(例如排序和查找等)写成模板,这样在后续的使用中不管数据结构中存放的是什么数据对象,算法应用于什么类型的数据对象,都不需要重新实现数据结构和算法,极大的提高了代码重用性。

​ 标准模板库 (Standard Template Library) 就是最为常用的数据结构和算法的模板集合,使用 STL 可以直接重用大多的标准数据结构和算法,而且能够获得相对较高的性能。

STL 中的基本概念

容器:可容纳各种数据类型的通用数据结构,都是类模板

迭代器:可用于依次存取容器中的元素,类似指针

算法:用来操作容器中元素的函数模板,例如可以使用 sort() 来对一个 vector 中的数据进行排序,使用 find() 来搜索一个 list 中的对象。算法的实现和它操作的数据对象无关,所以可以将算法应用于几乎任何数据结构。

int array[100]; // 容器
int* parr = array; // 使用 int* 类型的指针变量作为迭代器
sort(parr, parr+70); // 使用 sort() 算法作用于该容器

容器

​ 容器是可容纳各种数据类型(基本数据类型、对象等)的通用数据结构,都是类模板,分为三种类型:

  • 顺序容器vector, deque, list
  • 关联容器set, multiset, map, multimap
  • 容器适配器stack, queue, priority_queue

​ 使用容器时需要注意两点:

  • 对象被插入容器中时,被插入的是对象的一个复制品

  • 有些容器本身是存在顺序关系的即是已排序的,所以放入容器的对象所属的类一般需要重载 ==< 运算符。STL 中相等 == 和大小 < 的概念是可以自定义的,不局限于数值大小,示例如下:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;class A{int v;
    public:A(int n):v(n){};bool operator<(const A& a2) const{cout << v << "<" << a2.v << "?" << endl;return false;}bool operator==(const A& a2) const{cout << v << "==" << a2.v << "?" <<endl;return v == a2.v;}
    };int main(){A a[] = {A(1),A(2),A(3),A(4),A(5)};cout << binary_search(a,a+4,A(9)); // 折半查找return 0;
    }
    /*output: 说明 binary_search()方法没有使用 == 运算符只使用了<
    3<9?
    2<9?
    1<9?
    9<1?
    1
    */
    

顺序容器

​ 顺序容器是非排序的,而且其元素的插入位置与元素自身的值无关,数组便于查找,链表便于操作。

  • vector #include <vector> 一维动态数组:其元素在内存中是连续存放的,随机存取任何元素都可以在常数时间内完成,在该容器的尾部增删元素也几乎能够在常熟时间内完成具有较好的性能。
  • deque #include <deque> 双向队列:其元素在内存中是连续存放的,随机存取任何元素都可以在常数时间内完成,在该容器的两端增删元素也几乎能够在常熟时间内完成具有较好的性能。
  • list #include <list> 双向链表:其元素在内存中是不连续存放的,不支持随机存取,在该容器的任何位置增删元素几乎都能够在常熟时间内完成具有较好的性能。

关联容器

​ 关联容器的元素是排序的,插入元素需要根据相应的排序规则来确定插入位置的,在查找时具有较好的性能。关联容器通常使用平衡二叉树实现,其插入和检索的时间都是 O(log(N))O(log(N))O(log(N)) 。

  • set/multiset #include <set> 集合:set 集合中不允许存在相同的元素,multiset 集合中允许存在相同的元素。
  • map/multimap #include <map> 键值对集合:mapset 的不同在于前者存放的元素有且仅有两个成员变量 (first,second),一个名为 first,另一个名为 secondfirst 的值用来对整体元素进行从小到大的排序,并可以通过 first 快速检索元素。和 multiset 类似 multimapmap 的区别中允许存在相同 first 值的元素。

容器适配器

  • stack #include <stack> 栈:栈是项都有限序列,并满足序列中被删除、检索和修改的项都只能是最近插入序列的项,即栈顶的项。满足后进先出规则
  • queue #include <queue> 队列:(入队)插入只允许在尾部进行,(出队)删除、检索和修改只允许在头部进行。满足先进先出规则
  • priority_queue #include <queue> 优先级队列:优先级最高的元素总是第一个出队列

顺序容器和关联容器的成员函数

成员函数 函数作用
begin() 返回指向容器中第一个元素位置的迭代器
end() 返回指向容器中最后一个元素后面的位置的迭代器
rbegin() 返回指向容器中最后一个元素位置的迭代器
rend() 返回指向容器中第一个元素前面的位置的迭代器
erase() 从容器中删除一个或几个元素
clear() 从容器中删除所有元素

顺序容器的常用成员函数

成员函数 函数作用
front() 返回容器中第一个元素的引用
back() 返回容器中最后一个元素的引用
push_back() 在容器末尾增加新元素
pop_back() 删除容器末尾的元素
erase() 删除迭代器指向的元素,或删除一个区间,返回被删除元素后面的那个元素的迭代器

迭代器

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

​ 容器类的迭代器的定义方式如下,并使用 * 运算符访问迭代器所指向的元素:

容器类名::iterator 变量名; // 非const迭代器
容器类名::const_iterator 变量名; // const迭代器
* 迭代器变量名;

向前迭代器

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

#include <iostream>
#include <vector>
using namespace std;int main(){vector<int> v; // 空数组v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);vector<int>::const_iterator cit; // const 迭代器for(cit = v.begin(); cit != v.end(); ++cit){cout << *cit << ',';}cout << endl;vector<int>::reverse_iterator rit; // 反向迭代器for(rit = v.rbegin(); rit != v.rend(); ++rit){cout << *rit << ',';}cout << endl;vector<int>::iterator it; // 非 const 迭代器for(it = v.begin(); it != v.end(); ++it){*it += 1;cout << *it << ',';}cout << endl;return 0;
}

双向迭代器

​ 可以使用 ++/-- 运算符使迭代器指向容器中的下一个元素或上一个元素,同样也使用 * 运算符取迭代器所指向的元素。除此之外,双向迭代器可以用其他双向迭代器进行赋值 =,和与其他双向迭代器进行相等判定 ==/!=

随机访问迭代器

​ 除了具备双向迭代器的所有操作,随机访问迭代器还可以指定步长随机移动,例如 p +=/-= i 表示将该迭代器向后或向前移动 i 个元素;p +/- i 表示指向该迭代器之后或之前的第 i 个元素的迭代器;p[i] 表示该迭代器之后的第 i 个元素的引用。除了双向迭代器的相等判定之外,随机访问迭代器可以进行大小判定 <, <=, >, >=

容器和迭代器

容器 容器上的迭代器类别
vector 随机访问迭代器
deque 随机访问迭代器
list 双向迭代器
set/multiset 双向迭代器
map/multimap 双向迭代器
stack 不支持迭代器
queue 不支持迭代器
priority_queue 不支持迭代器

​ 容器支持的迭代器也直接限制其支持的算法,有的算法需要使用随机访问迭代器访问容器中的元素,例如 sort(), binary_search() 算法,那么 list 以及关联容器就不支持该算法。

算法

​ STL 中提供了能在各种容器中通用的算法,算法就是函数模板集合,大多数算法都定义在头文件 <algorithm> 中,算法不仅仅只可以对容器进行操作,也可以处理普通数组。

​ 算法通过迭代器来操作容器中的元素,一些算法不仅可以操作整个容器中的元素,也可以只操作容器中的一个局部区间,例如排序和查找算法,所以这类算法一般会带有两个参数,即起始元素的迭代器和终止元素的后一个元素的迭代器。有的算法的返回值是一个迭代器,例如 find() 算法的作用就是在容器中查找一个元素,并返回指向该元素的迭代器。

template <class Inlt, class T>
Inlt find(Inlt first, Inlt last, const T& val); // 查找区间左闭右开 [first, last),在该区间中找到等于 val 的元素并返回指向该元素的迭代器
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;int main(){int array[10] = {10,20,30,40};vector<int> v;v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);vector<int>::iterator it;it = find(v.begin(), v.end(), 3);if(it != v.end()){cout << *it << endl;}// find() 没有找到元素时,返回容器末尾迭代器it = find(v.begin(), v.end(), 9);if(it == v.end()){cout << "not found" << endl;}it = find(v.begin()+1,v.end()-2,2); // 完整容器:[1,2,3,4],查找的局部区间:[2,3)if(it != v.end()){cout << *it << endl;}// 算法操作普通数组int *parr = find(array,array+4,20);cout<< *parr << endl;return 0;
}

参考资料

程序设计与算法(三)C++面向对象程序设计

C++ 标准模板库 STL 概述相关推荐

  1. STL教程(一): 标准模板库--STL概述

    STL是C++通用库,主要由迭代器.算法.容器.仿函数.内存分配器和配接器组成. STL主要的主要功能都被声明在13个头文件中,它们分别是:< algorithm >.< deque ...

  2. C++中标准模板库STL基本概念

    0. 前言 C++语言的一大优势就是便于软件的重用,而重用体现在两方面: 1. 面向对象思想:继承和多态,标准类库 2. 泛程序设计(Generic Programming)思想:模板机制,标准模板库 ...

  3. C++ 标准模板库(STL)

    C++ 标准模板库(STL) C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列) ...

  4. c++标准模板库STL【快速查找】【最全】【常用】【语法】

    c++标准模板库STL[快速查找][最全][常用][语法] c标准模板库STL快速查找最全常用语法         vector- 变长数组         set-内部自动有序且不含重复元素     ...

  5. c语言stl模板,c/c++开发分享C++ 标准模板库 STL 顺序容器详解

    c++ 标准模板库 stl 顺序容器 容器 顺序性 重复性 支持迭代器 vector 动态数组 无序 可重复 随机访问迭代器 deque 双向队列 无序 可重复 随机访问迭代器 list 双向链表 无 ...

  6. 13 标准模板库STL【C++】

    13 标准模板库STL 13- 判断题 单选题 填空题 程序填空题 函数题 7-1 .查找电话号码 7-2 姓名排序 7-3 Score Processing 13+ 编程题 7-1 查找成绩并折算后 ...

  7. 第十章 标准模板库STL

    第十章 标准模板库STL 因为是在复习时重写的,无法在PTA上验证,编程题格式可能有误. 判断题 1.可以通过下标随机访问向量vector中的元素.(T) 2.当向量对象的内存用完之后,就会产生越界错 ...

  8. 标准模板库STL(Standard Template Library)

    标准模板库STL(Standard Template Library)指南 /*刘振飞liuzf@pku.org.cn 1999-10-20*/ / *版权所有 (C) 1999-2004 刘振飞li ...

  9. 蓝桥杯算法竞赛系列第0章——蓝桥必考点及标准模板库STL(上)(万字博文,建议抱走)

    欢迎来到:遇见蓝桥遇见你,不负代码不负卿! 目录 ​ 一.蓝桥必考点剖析 二.什么是STL 三.vector的常见用法详解 1.vector的定义 2.vector容器内元素的访问 (1).通过下标访 ...

最新文章

  1. 图片分类赛官方baseline解读!
  2. 三层交换机实现VLAN互通实例
  3. TureType/OpenType 字体瘦身、字体转换和字符替换
  4. STM32f103C8T6 bootloader设计
  5. HDU1247Hat’s Words(字典树)
  6. VB 6.0中的数据连接模块
  7. bzoj5252 [2018多省省队联测]林克卡特树
  8. c 中html上传文件大小,IOS微信内置浏览器对html标签input type=file上传的文件大小size错误?...
  9. 5.4Irvine32库
  10. Python 电子书下载列表
  11. python绘制中国地图(模仿中央气象台)
  12. 语义分割之pspnet
  13. csp ccf 202206-2 寻宝!大冒险!(70分超时的进)
  14. 信息安全管理体系ISO27001IT服务管理体系ISO20000(转)
  15. 【.Net码农】Stream 和 byte[] 之间的转换
  16. 计算机单位换换算,时间单位换算表与计算机单位换算
  17. 【参会指南】PPP全球数字资产投资峰会之金融科技区块链支持可持续发展
  18. python培训骗局
  19. 优矿API实现一个双均线策略
  20. 帆软报表在已经搭载服务器上开发_报表案例_数据报表开发_做报表的步骤_报表开发流程-帆软...

热门文章

  1. System.getProperty(user.dir)定位问题
  2. 移动博士血糖监测网络配置
  3. C语言C#参数对照表
  4. 自动化测试之流量回放技术
  5. icp备案和域名备案
  6. 命令行终端启动 emulator
  7. HTML画正方形钟表,html5 canvas绘制时钟表时间
  8. 客户最佳实践 | 容器云在证券行业的探索与实践(华泰证券管文琦 朱凯)
  9. arraycopy java_Java System arraycopy()方法
  10. 学术界的期刊编辑如何识别通过 ChatGPT 编写出来的论文?