deque容器和list容器学习

本文详细介绍了STL中的deque和list容器。包括deque的内存管理、迭代器实现及成员函数;list的内存结构和成员函数。并给出了选择deque、list和vector的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.deque简介:

deque容器同样是一种顺序容器,你可以了解你的元素的存储位置,你可以安排你的元素的存储位置。和vector相比,deque可以实现用常数的时间在容器头部插入元素。同样deque也没有容量的概念,这是因为deque可以动态地增加连续空间,而不需要像vector那样,因为之前的空间不够用,必须重新找一块内存,把数据拷贝过去,然后销毁之前的。

虽然deque也提供了随机迭代器,但其迭代器并不是像vector中是一个普通的指针,其实是实现很复杂,所以,除非你的需求特别适合deque,可以优先考虑vector(当然我们在这只说他们两个,是因为它们都有随机存取能力)

ps:(由于个人能力问题,我们只是从大体的角度去看这个容器,达到在工作中能够随心所欲地使用就可以了,具体的实现代码,就不去挖掘,明白实现思路就好了)


2.deque的实现

2.1 deque内存管理的基本思路:

 deque源码(删减的)

template <class T>

class deque {

protected:

  iteraotr    start;//表示第一个节点  iterator是一个迭代器,我们到时候再看这个类

  iteraotr     finish;// 表现最后一个节点

protected:

  T**  map;  // 指向map, map是一个连续的空间, 其每个元素都是一个指向缓冲区的指针

 size_type map_size;   // map容量

}

 

这样其实就很明白了,在deque的类中,我们有一个指向指针数组的指针,根据这个指针我们可以找到,指针数组所在的地址,这个数组其实叫中控器。中控器中的每个元素,分别指向一个固定大小的连续空间,这段空间叫做缓冲区,我们的数据其实就是存储在缓冲区中的。当我们的数据多到盛不下时,就可以重新分配一些连续的内存扩大容量。

2.2 deque的迭代器


可以看出来,deque要想支持随机访问,它的跌代器就要设计的很复杂,首先要能够找到数据存储的地址,为了方便找到下一个数据的位置,如果在同一个缓冲区内它必须有两个指向缓冲区头和尾的指针。如果下一个位置在另外的缓冲区内,则必须知道中控器的地址。其实,人家的实现只是一种思路,你可以疑惑为什么迭代器还要用两个first和last指针呢,如果 没有它们,我是不是同样的可以了解到当前指针的位置,是不是已经到了末尾?假设没有它们,我们要想知道当前的位置,就必须用当前位置的指针,与中控器元素的指针做减法与缓冲区大小作比较,而且有时,我们还可能从缓冲区的末尾开始增加元素,很费劲的。所以,多管理一些指针会很方便。

 

2.3 存有元素的deque内存状态


deque类中还有两个start 和finish迭代器可以看出,在存入元素时,开始的时候是从中控器的最中间开始存的,start和finish分别指向第一个元素和最后一个元素的下一个位置。

了解的也就这些吧,思路很好,要是写一个这样的容器,现在肯定还没有这样的水平。所以改日再看看代码吧。

 

3. deque的一些成员函数

c.assign(beg,end)    将[beg; end)区间中的数据赋值给c。

c.assign(n,elem)    将n个elem的拷贝赋值给c。

c. at(idx)     传回索引idx所指的数据,如果idx越界,抛出out_of_range。

c.back()    传回最后一个数据,不检查这个数据是否存在。

c.begin()   传回迭代器中的第一个数据。

c.clear()     移除容器中所有数据。

c.empty()   判断容器是否为空。

c.end()   指向迭代器中的最后一个数据地址。

c.erase(pos)     删除pos位置的数据,传回下一个数据的位置。

c.erase(beg,end)     删除[beg,end)区间的数据,传回下一个数据的位置。

c.front()     传回第一个数据

c.insert(pos,elem)     在pos位置插入一个elem拷贝,传回新数据位置c.insert(pos,n,elem)     在pos位置插入>n个elem数据。无返回值c.insert(pos,beg,end)    在pos位置插入在[beg,end)区间的数据。无返回值c.max_size()     返回容器中最大数据的数量。

c.pop_back()     删除最后一个数据

c.pop_front()    删除头部数据。

c.push_back(elem)    在尾部加入一个数据。

c.push_front(elem)    在头部插入一个数据。

c.rbegin()    传回一个逆向队列的第一个数据。

c.rend()   传回一个逆向队列的最后一个数据的下一个位置。

c.resize(num)     重新指定队列的长度。

c.size()   返回容器中实际数据的个数。


4.list的简介

stl中的list其实是一个双向循环列表,既然是链表,就有链表的特点。不支持随机访问,但是插入和删除操作效率高。主要是它还有一些对链表的操作,可以很好的锻炼我们的编程能力。当然,有机会专门要写一篇这种东西。


5.list的内存结构


在没有数据时,list只有个空的节点,这个结点两个指针指向自己。

6.list的一些成员函数

assign()给list赋值

back()返回最后一个元素

begin()返回指向第一个元素的迭代器

clear()删除所有元素

empty()如果list是空的则返回true

end()返回末尾的迭代器

erase()删除一个元素

front()返回第一个元素

insert()插入一个元素到list中

max_size()返回list能容纳的最大元素数量

merge()      合并两个list

pop_back()删除最后一个元素

pop_front()删除第一个元素

push_back()在list的末尾添加一个元素

push_front()在list的头部添加一个元素

rbegin()返回指向第一个元素的逆向迭代器

remove()从list删除元素

remove_if()按指定条件删除元素

rend() 指向list末尾的逆向迭代器

resize()改变list的大小

reverse()把list的元素倒转

size()返回list中的元素个数

sort()list排序

splice()合并两个list

swap()交换两个list

unique()删除list中重复的元素

 

7.vector、list、deque、三个容器的选择:

1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector 
2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list 
3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。


参考资料:《STL源码剖析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值