C++重点基础知识整理(四)--- STL容器

本篇内容为网络上的重点知识总结,参考了两位大佬的文章:文章一文章二

1、迭代器

1、什么是迭代器

要访问顺序容器和关联容器中的元素,需要通过“迭代器(iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。通过迭代器我们可以顺序访问一些容器中的各个元素。

2、迭代器和指针的区别

1、迭代器不是指针,是类模板,表现的像指针。他只是模拟了指针的一些功能,通过重载了指针的一些操作符(->,* ++,- -)等。
2、迭代器封装了指针,是一个“可遍历STL(Standard Template Library)容器内全部或部分元素”的对象,本质是封装了原生指针,是指针概念的一种提升,提供了比指针更高级的功能,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的++ ,- -操作。

3、迭代器产生的原因

Iterator类的访问方式就是把不同的集合类的访问逻辑抽象出来,使得不用暴露集合内部结构而达到循环遍历集合的效果。

(序列式容器)

2、Vector容器

3、queue容器

4、deque

1、deque容器的特点

1、deque(double-ended queue)双端队列
2、具有分段数组、索引数组,分段数组是存储数据的,索引数组是存储每段数组的首地址
3、向两端插入元素的效率较高
(若向两端插入元素,如果两端的分段数组未满,既可插入;如果两端的分段数组已满,
则创建新的分段函数,并把分段数组的首地址存储到deque容器中即可)。

4、 中间插入元素效率较低!

2、使用方法

用法 作用
q.begin(),q.end() 返回deque的首、尾迭代器
q.front(),q.back() 返回deque的首、尾元素
q.push_back() 从队尾入队一个元素
q.push_front() 从队头入队一个元素
q.pop_back() 从队尾出队一个元素
q.pop_front() 从队头出队一个元素
q.clear() 清空队列
除了这些用法之外,deque比queue更优秀的一个性质是它支持随机访问,即可以像数组下标一样取出其中的一个元素。即:q[i]。

3、priority_queue 容器

1、priority_queue 容器的特点

1、priority_queue在英文中是优先队列的意思。
队列是一种基本的数据结构。其实现的基本示意图如下所示:
在这里插入图片描述
而C++STL中的优先队列就是在这个队列的基础上,把其中的元素加以排序。其内部实现是一个二叉堆。所以优先队列其实就是把堆模板化,将所有入队的元素排成具有单调性的一队,方便我们调用。

2、priority_queue 容器的声明

priority_queue容器存放在模板库:#include里,使用前需要先开这个库。
这里需要注意的是,优先队列的声明与一般STL模板的声明方式并不一样。
大根堆声明方式:

#include<queue>
priority_queue<int> q;
priority_queue<string> q;
priority_queue<pair<int,int> > q;

小根堆的声明方式:

priority_queue<int,vector<int>,greater<int> >q;

3、priority_queue 容器的使用

用法 作用
q.top() 返回priority_queue的首元素
q.push() 向priority_queue中加入一个元素
q.size() 返回priority_queue当前的长度(大小)
q.pop() 从priority_queue末尾删除一个元素
q.empty() 返回priority_queue是否为空,1为空、0不为空
注意:priority_queue取出队首元素是使用top,而不是front,这点一定要注意!!

5、list容器

关联式容器

(1) 关联式容器都是有序的,升序排列,自动排序;

(2) 实现的是一个平衡二叉树,每个元素都有一个父节点和两个子节点,左子树的所有元素都比自己小,右子树的所有元素都比自己大;

6、set容器

1、set容器的特点

1、set容器的功用就是维护一个集合,其中的元素满足互异性。我们可以将其理解为一个数组。这个数组的元素是两两不同的。这个两两不同是指,如果这个set容器中已经包含了一个元素i,那么无论我们后续再往里假如多少个i,这个set中还是只有一个元素i,而不会出现一堆i的情况。这就为我们提供了很多方便。但是,需要额外说明的是,刚刚说集合是有无序性的,但是set中的元素是默认排好序(按升序排列)的。(set容器是红黑树实现的)
2、 如果要修改某一个元素值,必须先删除原有的元素,再插入新的元素。

2、set容器的使用

声明:

#include<set>
set<int> s;
set<char> s;
set<pair<int,int> > s;
set<node> s;
struct node{...};
//方法
s.empty();//empty()函数返回当前集合是否为空,是返回1,否则返回0.
s.size();//size()函数返回当前集合的元素个数。
s.clear();//clear()函数清空当前集合。
s.begin(),s.end();/*begin()函数和end()函数返回集合的首尾迭代器。
注意是迭代器。我们可以把迭代器理解为数组的下标。但其实迭代器是一种指针。
这里需要注意的是,由于计算机区间“前闭后开”的结构,begin()函数返回的指针指向的的确是集合的
第一个元素。但end()返回的指针却指向了集合最后一个元素后面一个元素。*/
s.insert(k);//insert(k)函数表示向集合中加入元素k。
s.erase(k);//rase(k)函数表示删除集合中元素k。
s.find(k);/*find(k)函数返回集合中指向元素k的迭代器。如果不存在这个元素,就返回s.end(),
这个性质可以用来判断集合中有没有这个元素。*/

6、multiset 容器

1、multiset容器的特点

1、multiset容器叫做:有序多重集合。
2、multiset的很多性质和使用方式和set容器差不了多少。而multiset容器在概念上与set容器不同的地方就是:set的元素互不相同,而multiset的元素可以允许相同。

2、与set不同的使用方法

s.erase(k);/*erase(k)函数在set容器中表示删除集合中元素k。
但在multiset容器中表示删除所有等于k的元素,时间复杂度变成了O(tot+logn),
其中tot表示要删除的元素的个数。*/

//删除一个元素而不全部删除
if((it=s.find(a))!=s.end())
	s.erase(it);

7、map 、multimap容器

1、特点

(1) map为单重映射、multimap为多重映射;

(2) 主要区别是map存储的是无重复键值的元素对,而multimap允许相同的键值重复出现,既一个键值可以对应多个值。

(3) map内部自建了一颗红黑二叉树,可以对数据进行自动排序,所以map里的数据都是有序的,这也是我们通过map简化代码的原因。

(4)自动建立key-value的对应关系,key和value可以是你需要的任何类型。

(5) key和value一一对应的关系可以去重。

去重类问题:可以打乱重新排列的问题,有清晰的一对一关系的问题

2、map 、multimap容器的使用

1、声明

#include<map>
map<int,char> mp;
map<int,char, op> m;  //op为排序规则,默认规则是less<T>

2、方法

m.at(key);

m[key];

m.count(key);

m.max_size(); //求算容器最大存储量

m.size();  //容器的大小

m.begin();

m.end();

m.insert(elem);

m.insert(pos, elem);

m.insert(begin, end);

8、pair类模板

1、特点

1、主要作用是将两个数据组成一个数据,用来表示一个二元组或一个元素对,两个数据可以是同一个类型也可以是不同的类型。当需要将两个元素组合在一起时,可以选择构造pair对象。
2、set的insert返回值为一个pair<set::iterator,bool>。bool标志着插入是否成功,而iterator代表插入的位置,若该键值已经在set中,则iterator表示已存在的该键值在set中的位置。如:

set<int> a;

           a.insert(1);

           a.insert(2);

           a.insert(2);//重复的元素不会被插入;

注意一下:make_pair()函数内调用的仍然是pair构造函数
set中的erase()操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意

2、pari类模板的使用

1、创建pair对象:

pair<int, float> p1;   //调用构造函数来创建pair对象

make_pair(1,1.2);      //调用make_pair()函数来创建pair对象

2、pair对象的使用:

pair<int, float> p1(1, 1.2);
cout<< p1.first << endl;
cout<< p1.second << endl;

3、顺序遍历

set<int> a;
set<int>::iterator it=a.begin();
for(;it!=a.end();it++){
    cout<<*it<<endl;
 }

4、反序遍历

set<int> a;
set<int>::reverse_iterator rit=a.rbegin();
for(;rit!=a.rend();rit++)
cout<<*rit<<endl;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值