容器种类

  • 序列容器(数组,链表)

    • Vector, deque, list, forward list, array
  • 关联容器(二叉树),总是有序的
    • set, multiset根据值排序,元素值不能修改
    • map, multimap根据key排序,键值不能修改
  • 无序容器(hash 表)
    • 无序set/multiset
    • 无序map/multimap

序列容器

Vector

vector<int> vec;   // vec.size() == 0
vec.push_back(4);
vec.push_back(1);
vec.push_back(8); // vec: {4, 1, 8}; vec.size() == 3 // Vector特定的操作:
cout << vec[2]; // 8 (没有范围检查)
cout << vec.at(2); // 8 (超出范围会抛range_error exception异常) for (int i; i < vec.size(); i++) {
cout << vec[i] << " "; for (list<int>::iterator itr = vec.begin(); itr!= vec.end(); ++itr)
cout << *itr << " "; for (it: vec) // C++ 11
cout << it << " "; // Vector是内存中一个动态分配的连续的数组
int* p = &vec[0]; p[2] = 6; // 所有容器共有的一些成员函数
// vec: {4, 1, 8}
if (vec.empty()) { cout << "Not possible.\n"; } cout << vec.size(); // 3 vector<int> vec2(vec); // 拷贝构造, vec2: {4, 1, 8} vec.clear(); // 删除所有元素; vec.size() == 0 vec2.swap(vec); // 交换,vec2变成空的,vec有3个元素 // 注:没有抽象带来的开销,非常高效 /* Vector的特性:
* 1. 在末尾插入/删除很快: O(1)
* 2. 在其他地方插入/删除s慢: O(n)
* 3. 搜索慢: O(n)
*/

Deque

deque<int> deq = { 4, 6, 7 };
deq.push_front(2); // deq: {2, 4, 6, 7}
deq.push_back(3); // deq: {2, 4, 6, 7, 3} // Deque接口跟vector类似
cout << deq[1]; // 4 /* 特性:
* 1. 在首尾插入/删除快
* 2. 中间插入/删除慢: O(n)
* 3. 搜索慢: O(n)
*/

List

 *  -- 双向链表
* 元素储存在内存不同的地方,cache会经常miss。很多STL实现会将其元素放到一起,但即使如此因为包含了太多指针,会消耗更多的内存(意味着更多的cache miss和page fault)
*/
list<int> mylist = {5, 2, 9 };
mylist.push_back(6); // mylist: { 5, 2, 9, 6}
mylist.push_front(4); // mylist: { 4, 5, 2, 9, 6} list<int>::iterator itr = find(mylist.begin(), mylist.end(), 2); // itr -> 2
mylist.insert(itr, 8); // mylist: {4, 5, 8, 2, 9, 6}
// O(1), 比vector/deque更快
itr++; // itr -> 9
mylist.erase(itr); // mylist: {4, 8, 5, 2, 6} O(1) /* 特性:
* 1. 任何地方插入/删除快: O(1)
* 2. 搜索慢: O(n)
* 3. 没有随机访问,即没有 [] 运算符
*/ // 拼接速度快
mylist1.splice(itr, mylist2, itr_a, itr_b ); // O(1)

Array

// 不能改变大小,不能元素个数的Array是不同类型
int a[3] = {3, 4, 5};
array<int, 3> a = {3, 4, 5};
a.begin();
a.end();
a.size();
a.swap();
array<int, 4> b = {3, 4, 5};

关联容器

  • 基于二叉树,总是排序的,默认基于 < 排序
  • 没有push_back(), push_front()

set和multiset

// 元素不能重复

  set<int> myset;
myset.insert(3); // myset: {3}
myset.insert(1); // myset: {1, 3}
myset.insert(7); // myset: {1, 3, 7}, O(log(n)) set<int>::iterator it;
it = myset.find(7); // O(log(n)), it指向7
// 序列容器没有find函数
pair<set<int>::iterator, bool> ret;
ret = myset.insert(3); // 不插入新元素
if (ret.second==false)
it=ret.first; // "it"当前指向元素3 myset.insert(it, 9); // myset: {1, 3, 7, 9} O(log(n)) => O(1),it作为插入元素位置的一个提示,并不是实际插入位置
// it 指向3
myset.erase(it); // myset: {1, 7, 9} myset.erase(7); // myset: {1, 9}
// 注:序列容器没有这种根据元素值删除元素的erase // multiset允许元素重复的set
multiset<int> myset; // set/multiset: 元素值都是不能修改的
*it = 10; // *it只读 /* 特性:
* 1. 搜索快: O(log(n))
* 2. 因为也是通过指针联系(cache miss和page fault的问题),遍历慢 (相比vector & deque)
* 3. 没有随机访问,即没有 [] 运算符
*/

map和multimap

/*
* map
* - key值不能重复
*/
map<char,int> mymap;
mymap.insert ( pair<char,int>('a',100) );
mymap.insert ( make_pair('z',200) ); map<char,int>::iterator it = mymap.begin();
mymap.insert(it, pair<char,int>('b',300)); // "it"只是一个提示 it = mymap.find('z'); // O(log(n)) // showing contents:
for ( it=mymap.begin() ; it != mymap.end(); it++ )
cout << (*it).first << " => " << (*it).second << endl; // multimap允许键值重复
multimap<char,int> mymap; // map/multimap:
// -- 键值不能修改
// type of *it: pair<const char, int>
(*it).first = 'd'; // Error // 为何叫“关联”容器
// 因为value和key是关联的,set是特殊的map,value等于key

无序容器(C++ 11)

  • 无序的set/multiset
  • 无序的map/multimap
  • 顺序是未定义的,可能随时间改变

/*
* 基本类型和string都定义了默认的hash函数
*
* 没有下标操作[]和at()
* 没有push_back()和push_front()
*/

unordered_set<string> myset = { "red","green","blue" };
unordered_set<string>::const_iterator itr = myset.find ("green"); // O(1)
if (itr != myset.end()) // 重要的检查
cout << *itr << endl;
myset.insert("yellow"); // O(1) vector<string> vec = {"purple", "pink"};
myset.insert(vec.begin(), vec.end()); // Hash表特定的APIs:
cout << "load_factor = " << myset.load_factor() << endl; // 负载因子:总元素和总桶数的比值
string x = "red";
cout << x << " is in bucket #" << myset.bucket(x) << endl; // x位于哪个桶
cout << "Total bucket #" << myset.bucket_count() << endl; // 总的桶数 // 无序multiset,无序map和multimap也是类似 // hash冲撞 => 性能退化 /* 无序容器的特性:
* 1. 在任何位置搜索/插入都最快: O(1)
* 关联容器O(log(n))
* vector, deque O(n)
* list插入O(1) , 搜索O(n)
* 2. Unorderd set/multiset: 元素值不能改变
* Unorderd map/multimap: key不能改变
*/

Associative Array

/*
* 一般指的是map和unordered map
*/
unordered_map<char, string> day = {{'S',"Sunday"}, {'M',"Monday"}}; cout << day['S'] << endl; // 没有范围检查
cout << day.at('S') << endl; // 有范围检查 vector<int> vec = {1, 2, 3};
vec[5] = 5; // Compile Error day['W'] = "Wednesday"; // Inserting {'W', "Wednesday}
day.insert(make_pair('F', "Friday")); // Inserting {'F', "Friday"} day.insert(make_pair('M', "MONDAY")); // key已经存在,插入失败
day['M'] = "MONDAY"; // 可以通过下标修改值 void foo(const unordered_map<char, string>& m) {
//m['S'] = "SUNDAY";
//cout << m['S'] << endl; //编译出错,下标操作有写权限,编译器看到以为要对const变量进行写操作
auto itr = m.find('S'); //使用find替代
if (itr != m.end())
cout << *itr << endl;
}
foo(day); //关于Associative Array:
//1. 搜索时间: unordered_map, O(1); map, O(log(n));
//2. 但是Unordered_map可能退化为O(n);
//3. 不能使用multimap和unordered_multimap, 它们的key不唯一,也没有下标操作[]

容器适配器

  • 为了满足某种特殊需要,提供受限制的接口
  • 通过基本的容器类实现
 *
* 1. 栈 stack: LIFO, push(), pop(), top()
*
* 2. 队列 queue: FIFO, push(), pop(), front(), back()
*
* 3. 优先级队列 priority queue: 第一个元素总是具有最高优先级
* push(), pop(), top()
*/

另一种容器分类的方法

 *
* 1. 基于数组的容器: vector, deque
*
* 2. 基于结点的容器: list + associative containers + unordered containers
*
* 基于数组的容器会使指针失效:
* - 原生指针,迭代器,引用
*/ vector<int> vec = {1,2,3,4};
int* p = &vec[2]; // p points to 3
vec.insert(vec.begin(), 0);
cout << *p << endl; // 2, or ?
// 运气好,打印2;运气不好,未定义

STL基础--容器的更多相关文章

  1. STL List容器

    转载http://www.cnblogs.com/fangyukuan/archive/2010/09/21/1832364.html 各个容器有很多的相似性.先学好一个,其它的就好办了.先从基础开始 ...

  2. STL之容器适配器queue的实现框架

    说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章STL之容器适配器stack的实现框架已经介绍了STL是怎样借助基础容器实现一种经常使用的数据结构stack (栈),本文介绍下第二种STL ...

  3. STL之容器适配器stack的实现框架

    说明:本文仅供学习交流,转载请标明出处,欢迎转载! 一提到适配器(adapter).我们就想到了早期用电话线上网所用的调制解调器,俗称"猫"."猫"的作用是实现 ...

  4. c++复习:STL之容器

    1 STL的string 1 String概念 string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都可以用来表示字 ...

  5. 详解C++ STL priority_queue 容器

    详解C++ STL priority_queue 容器 本篇随笔简单介绍一下\(C++STL\)中\(priority_queue\)容器的使用方法和常见的使用技巧. priority_queue容器 ...

  6. 2.7 C++STL list容器详解

    文章目录 2.7.1 引入 2.7.2代码示例 2.7.3代码运行结果 总结 2.7.1 引入 STL list 容器,又称双向链表容器,即该容器的底层是以双向链表的形式实现的.这意味着,list 容 ...

  7. C++ STL vector容器学习

    STL(Standard Template Library)标准模板库是C++最重要的组成部分,它提供了一组表示容器.迭代器.函数对象和算法的模板.其中容器是存储类型相同的数据的结构(如vector, ...

  8. STL基础知识

    一,STL的组成 1.什么是STL STL(Standard Template Library)标准模板库的简称,是由惠普开发的一系列软件的总称,STL现在是C++的一部分,已经被构建于编译系统之内, ...

  9. STL的容器算法迭代器的设计理念

    1) STL的容器通过类模板技术,实现数据类型和容器模型的分离. 2) STL的迭代器技术实现了遍历容器的统一方法:也为STL的算法提供了统一性. 3) STL的函数对象实现了自定义数据类型的算法运算 ...

随机推荐

  1. python import 其他 package的模块

    https://blog.csdn.net/luo123n/article/details/49849649 http://blog.habnab.it/blog/2013/07/21/python- ...

  2. IK 中文分词器

    链接:https://github.com/wks/ik-analyzerIKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始,IKAna ...

  3. lesson6-图像分割-小象c

    显著性检测:1)显著性物体检测-最能引起视觉注意的物体区域2)注视点预测:人类视觉注意机制 视觉注意机制的两种机制:1)自底而上基于数据驱动的注意机制,如颜色.边缘 2)自上而下基于任务驱动的目标的注 ...

  4. UE4开发安卓遇到的坑

    做个记录,方便以后自己查询. 1.  打包后,应用出现缺乏google key的问题. 理论上,这个网站可以解决:https://wiki.unrealengine.com/How_To_Sign_U ...

  5. LeetCode - Minimum Area Rectangle

    Given a set of points in the xy-plane, determine the minimum area of a rectangle formed from these p ...

  6. 我的TDD实践---TDD概念篇

    “我的TDD实践”系列之TDD概念篇 写在前面: 我的TDD实践这几篇文章主要是围绕测试驱动开发所展开的,其中涵盖了一小部分测试理论,更多的则是关注工具的使用及环境的搭建,做到简单实践先行,后理论专精 ...

  7. jsp&el&jstl mvc和三层架构

    jsp:java在html中插入java 一.JSP技术 1.jsp脚本和注释 jsp脚本:(翻译成servlet,源码位置apache-tomcat-7.0.52\work\Catalina\loc ...

  8. C++中的继承和多继承

    一.学习笔记 1.继承 class Student : public Person { ... } 2.继承时权限派生类中可以直接访问父类的protected成员,但是不能访问其private成员,若 ...

  9. css易错点总结

    传智老师说:找工作要问调不调IE6,同样的工作待遇,如果不用调IE6开12000工资,要调IE6,直接加价到15000,因为调IE6能累死人,气死人. 行高要在字体后面,如下: 正确:font:400 ...

  10. 论 大并发 下的 乐观锁定 Redis锁定 和 新时代事务

    在 <企业应用架构模式> 中 提到了 乐观锁定, 用 时间戳 来 判定 交易 是否有效, 避免 传统事务 的 表锁定 造成 的 瓶颈 . 在 现在的 大并发 的 大环境下, 传统事务 及其 ...