数据结构 (STL)丨梦中的情人

  • 数据结构 by STL

你用的最多的STL中的数据结构是什么?(最多选择四项)

  • 栈丨stack
  • 队列丨queue (包括衍生的priority_queue)
  • 双向队列丨deque
  • vector
  • 集合丨set
  • 地图丨map
  • 链表丨list
  • array
  • 其他,请补充(应该没其他的了吧

0 投票人

  • 一维数组:应该没人不知道吧

  • 栈 (stack) :
    栈 (stack) 是限定仅在表尾进行插入或者删除的线性表。对于栈来说,表尾端称为栈顶(top),表头端称为栈底(bottom)。不含元素的空表称为空栈。因为栈限定在表尾进行插入或者删除,所以栈又被称为后进先出的线性表(简称LIFO:Last in, First out 结构)。

//// 表达式计算,神坛上の栈 ////

//8829 计算表达式
//1031 表达式的计算
//有兴趣的可以去洛谷加以钻研
/*
#include<stack>
stack<int> s;
stack<string> s;
stack<node> s;
s.empty();         //如果栈为空则返回true, 否则返回false;
s.size();          //返回栈中元素的个数
s.top();           //返回栈顶元素, 但不删除该元素
s.pop();           //弹出栈顶元素, 但不返回其值
s.push();          //将元素压入栈顶
*/

可惜的是,后进先出,多少有些没素质(bushi

  • 队列(queue):
    队列是一个先进先出的数据结构
    联想一下链表,在单链表中,只能对表尾进行插入,对表头进行结点的删除,这样强限制性的链表,就是所说的队列。也就是说,队列是限定在表的一端进行插入,表的另一端进行删除的数据结构。

  • 去买票排队,每一列队伍都有一个队尾和队首,先来的先买票,后来的后买,买好的就从队首出去,新来买票的就需要从队尾继续排队。是不是比栈有素质多了(bushi

//// 队列 queue丨模拟の神 ////

/*
#include<queue>
queue<int> q;
queue<string> q;
queue<node> q;
q.empty()               //如果队列为空返回true,否则返回false
q.size()                //返回队列中元素的个数
q.pop()                 //删除队列首元素但不返回其值
q.front()               //返回队首元素的值,但不删除该元素
q.push()                //在队尾压入新元素
q.back()                //返回队列尾元素的值,但不删除该元素
*/

可他不能以下标遍历(此处鞭尸 栈_stack

  • 神秘のdeque
    deque(双端队列)是double-ended queue 的一个不规则缩写。deque是具有动态大小的序列容器,可以在两端(前端或后端)扩展或收缩。

  • 特定的库可以以不同的方式实现deques,通常作为某种形式的动态数组。但是在任何情况下,它们都允许通过随机访问迭代器直接访问各个元素,通过根据需要扩展和收缩容器来自动处理存储。

  • deque上常见操作的复杂性(效率)如下:

  1. 随机访问 - 常数 O(1)
  2. 在结尾或开头插入或移除元素 - 摊销不变 O(1)
  3. 插入或移除元素 - 线性 O(n)

//// 从单向变双向丨deque ////

#include <deque> 
deque<int> a; //定义一个int类型的双端队列a
deque<int> a(10); //定义一个int类型的双端队列a,并设置初始大小为10
deque<int> a(10, 1); //定义一个int类型的双端队列a,并设置初始大小为10且初始值都为1
deque<int> b(a); //定义并用双端队列a初始化双端队列b
deque<int> b(a.begin(), a.begin()+3); //将双端队列a中从第0个到第2个(共3个)作为双端队列b的初始值
//-------------------------------------------------------------------
deq.size() //容器大小
deq.max_size() //容器最大容量
deq.resize() //更改容器大小
deq.empty() //容器判空
deq.shrink_to_fit() //减少容器大小到满足元素所占存储空间的大小
deq.front() //访问第一个元素
deq.back() //访问最后一个元素
deq.push_back() //尾部增加元素
deq.push_front() //前端增加元素
deq.pop_back() //删除尾部元素
deq.pop_front() //删除前端元素
deq.emplace_front() //头部插入
deq.emplace_back() //尾部插入
deq.insert() //任意位置插入一个元素 
deq.erase() //任意位置删除元素
dep.at() //检测越界并访问

双端操作的奇妙无法想象!

  • vector

  • vector是一个连续的线性空间,就像数组一样,区别于数组之处在于vector是可以对数组的大小进行动态修改的。但是在访问和操作上也可以像数组一样提供一种指针的访问方式,那么这就是vector迭代器,但是迭代器千万不可以被理解为它就是指针。

  • vector这个容器理解起来就像一个大小可变的数组,与数组不同的地方就是数组是一块静态的空间,而vector是一块动态的空间,随着元素的加入,vector的内部机制会自行扩充空间大小以收纳更多的元素。

//// 万金油 vector ////

/*
#include<vector>
vector<int> v1;
vector<node> v2;
vector<string> v3;
vector<vector<int> >;  //注意空格 //这里相当于二维数组int a[n][n];
vector<int> v5 = { 1,2,3,4,5 };
vector<string> v6 = { "my","name","is","Badcen" };
//初始化
vector<int> v7(5, -1); //初始化为-1,-1,-1,-1,-1。
vector<string> v8(3, "hi");
//第一个参数是数目,第二个参数是要初始化的值
vector<int> v9(10); //默认初始化为0
vector<int> v10(4); //默认初始化为空字符串
*/

确实是个万能数据结构(确信

  • 集合 set
  • set就是集合的意思,集合的特点就是不会出现重复的内容。一般用来作查重或去重操作。

////set:欢乐的世界////

#include<set>
set<int> se;
set<string> se;
set<node> se;
se.insert() //插入元素
se.count() //判断容器中是否存在某个元素
se.size() //返回容器的尺寸,也可以元素的个数
se.erase() //删除集合中某个元素
se.clear() //清空集合
se.empty() //判断是否为空
se.begin() //返回第一个节点的迭代器
se.end() //返回最后一个节点加1的迭代器
se.rbegin() //反向迭代器
se.rend() //反向迭代器
se.find() //查找某个指定元素的迭代器
se.lower_bound() //二分查找第一个不小于某个值的元素的迭代器
se.get_allocator() //返回集合的分配器
se.swap() //交换两个集合的变量
se.max_size() //返回集合能容纳元素的最大限值

他不能直接访问元素,但有很多不知名数据结构也不行,不寒颤( stack & queue :6

  • 地图 map
    现实中的数据很多是关联的,例如书本名称和价格,每条数据都含有两部分:
  1. 信息学竞赛一本通 :¥80
  2. 高等数学 :¥27.5
  3. 生物信息分析 :¥35.5
  • 我们可以使用map存储这类一对一的数据:
    第一个可以称为关键字(key),每个关键字只能在map中出现一次;
    第二个可以称为该关键字的值(value);

  • 另外需要注意的是,使用 map 容器存储的各个键-值对,键的值既不能重复也不能被修改。换句话说,map 容器中存储的各个键值对不仅键的值独一无二,键的类型也会用 const 修饰,这意味着只要键值对被存储到 map 容器中,其键的值将不能再做任何修改。

//// map:新华字典检索表 ////

#include<map>
map<int,int> m;
m.insert({a,b});  //添加元素 //等价于 m.insert(pair<int,int> (a,b));
//map中key的值是唯一的,如果插入一个已经存在的key值会导致原先值的覆盖
m.erase(i);    //删除 m[i] //括号内为key值,也就是左值
m[i] = n; //修改元素
ans = m[i] //直接通过key值查找元素
ans = find(12)->first;    //通过value值找key值
ans = find(1)->second;    //通过key值找value值
m.clear();                //清除所有元素
m.empty();                //如果为空返回1,负责返回0
m.size();                 //返回容器的元素个数
m.max_size();               //返回容器可以容纳的最大元素
m.begin()->first;         //结果为容器的第一个元素的key值
m.begin()->second;         //结果为容器的第一个元素的value值

MLE说不定可以这么解决?

  • 链表 list
  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
  3. list与forward_list非常相似:主要不同在于forward_list是单链表,只能单方向迭代。
  4. 与其他的序列式容器相比(array,vector,deque),list在任意位置进行插入、移除元素的执行效率更好。
  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置。
  6. list还需要一些额外的空间,以保存每个节点的相关联信息。

//// 难以捉摸的下一元素:list ////


不想打出来qwq(不会真有人用链表吧

  • array
    array是序列式容器,类似于C语言的数组,是固定大小的,一旦定义完成后就无法进行扩容或收缩。

////array:无名的数据结构////

begin	返回容器中第一个元素的迭代器
end	返回容器中最后一个元素之后的迭代器
rbegin	返回指向最后一个元素的迭代器
rend	返回指向第一个元素之前的迭代器
size	返回 容器中当前元素的数量
max_size	返回容器可容纳的最大数量
empty	判断容器是否为空
at	返回容器在n处的引用,有错误检测
front	返回容器的第一个元素的引用
back	返回容器的最后一个元素的引用
data	返回指向首个元素的指针
fill	填充元素
swap	交换容器内的元素

array可以用来创造多维数组,但我不放(懒qwq

  • 其实这里的大多数数据结构我们上课都手打过(可恶被骗了),各种数据结构我们除了需要会使用,还需要理解其原理

  • 最后,感谢STL的贡献!(翻译:我很懒不想手打

9 个赞

bitset???

4 个赞

STL没学过(悲

4 个赞

DQ都si了,提他干嘛 :sweat_smile: :sweat_smile:

2 个赞

哇塞,啥时候我也能学到!! :grinning:

4 个赞

deque为什么没人?它挺好用的

2 个赞

平等地对待每一个数据结构(doge

1 个赞