当前位置: 首页 > news >正文

网站的落地页万网网站建设步骤

网站的落地页,万网网站建设步骤,wordpress架设专题类网站,盐城网站制作🔥拾Ծ光:个人主页 👏👏👏欢迎来到我的专栏:《C》,《C类和对象》,《数据结构》,《C语言》 想必大家都很好奇:为什么STL中实现了vector容器和list容器后&#…

  

                                                       🔥拾Ծ光:个人主页

👏👏👏欢迎来到我的专栏:《C++》,《C++类和对象》,《数据结构》,《C语言》

想必大家都很好奇:为什么STL中实现了vector容器和list容器后,还要实现一个deque容器呢?接下来我们就来看看这个容器到底有什么神奇的地方,在此之前,我们先讨论一下vector和list的不同之处:

目录

一、vector容器和list容器对比

1、内存结构对比⭐️

2、对于插入数据时的时间复杂度对比分析:

3、对于删除数据时的时间复杂度对比分析:

4、迭代器特性对比⭐️

5、总结:

二、双端队列——deque(了解)

1、什么是deque?

2、deque的特殊结构

3、常用接口说明

4、deque的缺陷

三、总结


一、vector容器和list容器对比

对于这两个容器的区别也是面试中的高频考点(⭐️⭐️⭐️)

两者的本质区别源于底层实现(核心数据结构与内存布局),这直接决定了它们的性能特性:

1、内存结构对比⭐️

容器底层数据结构⭐️内存布局⭐️核心特点⭐️
vector动态数组连续内存空间元素存储在连续的内存块中,当空间不足时会自动扩容(通常扩容为原大小的 1.5~2 倍,拷贝旧元素到新空间)

(1)支持随机访问

(2)内存局部性好(缓存利用率高);

(3)扩容可能产生内存浪费和拷贝开销

list双向链表非连续内存节点每个元素存储在独立的节点中,节点包含「数据域」和两个「指针域」(分别指向前驱和后继节点),节点在内存中分散存储

(1)不支持随机访问;

(2)内存局部性差;

(3)插入 / 删除操作无需移动元素,仅需修改指针

2、对于插入数据时的时间复杂度对比分析:

插入位置vector 时间复杂度list 时间复杂度核心原因
尾部(push_back)

O (1)

( amortized,均摊)

O(1)

vector 尾部插入:若内存充足,直接在末尾添加;若需扩容,需拷贝旧元素(O (n)),但均摊后为 O (1);

list 尾部插入:仅需创建新节点,修改尾节点指针,无需移动元素

头部(push_front)O(n)O(1)

vector 头部插入:需将所有元素向后移动 1 位,覆盖新元素位置;

list 头部插入:仅需创建新节点,修改头节点指针,无需移动元素

中间(指定迭代器位置)O(n)O(1)

3、对于删除数据时的时间复杂度对比分析:

删除位置vector 时间复杂度list 时间复杂度核心原因
尾部(pop_back)O(1)O(1)

vector 尾部删除:仅需将「有效元素个数」减 1,无需修改内存;

list 尾部删除:修改尾节点前驱的指针,释放尾节点内存

头部(pop_front)O(n)O(1)

vector 头部删除:需将所有元素向前移动 1 位,覆盖被删除元素;

list 头部删除:修改头节点后继的指针,释放头节点内存

中间(指定迭代器位置)O(n)O(1)

vector 中间删除:需将删除位置后的元素向前移动,填补空缺;

list 中间删除:若已拿到迭代器,仅需修改前后节点指针,释放当前节点

4、迭代器特性对比⭐️

特性vector 迭代器list 迭代器
迭代器类型随机访问迭代器(RandomAccessIterator)双向迭代器(BidirectionalIterator)
支持的操作支持++、--、 +-+=-=[] 等算术操作(如 it + 5 直接跳 5 个元素)仅支持 ++-- 操作(只能逐个移动)
迭代器失效⭐️

- 扩容时,所有迭代器、指针、引用均失效;

- 插入 / 删除中间元素时,插入 / 删除位置后的迭代器失效

- 仅「被删除节点的迭代器」失效;

- 插入元素时,所有迭代器均有效

5、总结:

优先选择 vector 的场景:

1、需要频繁随机访问元素(如通过下标读取、排序、二分查找 ——vector 支持 std::sortlist 需用自身的 sort() 成员函数);

2、插入 / 删除操作主要在尾部(如实现栈、动态数组);

3、对内存局部性要求高(如高频访问元素,依赖缓存加速);

4、存储小数据类型,希望控制内存开销。

优先选择 list 的场景:

1、需要频繁在头部或中间插入 / 删除元素(如实现双向队列、频繁调整顺序的列表);

2、不依赖随机访问,仅需顺序遍历;

3、对迭代器稳定性要求高(如遍历中频繁插入 / 删除,避免迭代器失效);

4、存储大数据类型(指针开销占比低,插入 / 删除无需移动大元素)。

二、双端队列——deque(了解)

1、什么是deque?

通过上面的对比,我们知道,vector有随机访问,缓存利用率高等特点,但插入删除操作时间复杂度为O(N);而对于list恰好相反,不支持随机访问,缓存利用率低,但插入删除操作时间复杂度仅为O(1)。不难发现,这两个容器的优劣势几乎是相对的,那么有没有一个容器能够将这两个容器的优劣势互补一下呢!

deque(Double-Ended Queue,双端队列)是 C++ STL(标准模板库)中一种双向动态数组容器,核心特点是支持在首尾两端高效插入和删除元素,同时兼顾对中间元素的随机访问能力(但效率低于 vector)。

deque的特殊结构就刚好结合了 vector(随机访问)和 list(首尾操作高效)部分优势,是一种平衡了多种需求的容器。

2、deque的特殊结构

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端 进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与 list比较,空间利用率比较高。

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个 动态的二维数组,其底层结构如下图所示:

deque底层有一个中控器(map数组)存储每个buffer小数组的地址,同时,还有4个迭代器来维护buffer数组,其中,node指向buffer数组,first指向buffer数组的起始位置,cur指向buffer数组的最后一个有效数据的下一个位置,last指向buffer数组末尾的下一个位置。

那deque是如何借助其迭代器维护其假想连续的结构呢?

比如要在中控数组map中node指针指向的buffer1插入数据,就要先判断cur迭代器是否与last迭代器指向位置相同,防止越界,若未越界,则在cur迭代器指向的位置插入,然后cur++;反之,则在node迭代器后面的一个迭代器指向的buffer数组插入,若中控数组已经满了,就先扩容,然后插入。

3、常用接口说明

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩 容时,也不需要搬移大量的元素,因此其效率是必vector高的。 与list比较,deque底层是连续空间,空间利用率比较高,不需要存储额外字段

而我们知道,栈(stack)——先进后出,其最常用的操作就是尾删,尾插,获取栈顶数据等;队列(queue)——先进先出,其最常用的操作就是头删,尾插,获取队头或队尾数据。对于这些操作,deque容器由于结合了vector和lis的部分优势,而恰好能够满足,所以deque容器作为stack和queue这种容器适配器(这个我会专门为大家介绍)的底层数据结构就非常完美。

所以,下面我们介绍deque的头/尾插,头/尾删等操作,其他操作由于deque的缺陷而消耗很大,我们并不推荐使用,所以也并不作介绍,有兴趣可以自己查看文档。

        接口函数                                  功能
push_front (const value_type& val)
                                头插val
push_back (const value_type& val)
                                尾插val
pop_front()
                                头删
pop_back()
                                尾删
size()
                       获取有效数据个数
front()
                        返回第一个数据
back()
                       返回最后一个数据
empty()
                               判空
deque<int> dq; // 实例化对象dq
// 尾插
dq.push_back(1);
dq.push_back(2);
// 头插
dq.push_front(10);
// 获取队头数据
int top = dq.front();
// 获取队尾数据
int end = dq.back();
// 头删
dq.pop_front();
// 尾删
dq.pop_back();
// 获取有效数字个数
size_t n = dq.size();

下面我提供一段测试代码,我们看对比一下对于vector和deque容器实例化的数组,用sort函数排序,那个更快呢?

#include<ctime> // time函数头文件
#include<cstdlib> // rand函数头文件
#include<algorithm> // sort头文件
void test1() {srand(time(0));int N = 100000;vector<int> v; deque<int> de;for (int i = 0; i < N; i++) {auto e = rand() + i;v.push_back(e);de.push_back(e);}int begin1 = clock();sort(v.begin(), v.end()); // 排序v对象的数据int end1 = clock(); int begin2 = clock();sort(de.begin(), de.end()); // 排序de对象的数据int end2 = clock();cout << "vector sort" << end1 - begin1 << endl;cout << "deque sort" << end2 - begin2 << endl;
}

输出结果

可以看到,vector数组的速度几乎是deque的5倍。

4、deque的缺陷

deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其 是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实 际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。

同时,在中间位置插入或删除数据时,如果原来的数据较多,就需要移动数据,但是由于deque的特殊结构,移动数据更加复杂,消耗也很大。

三、总结

deque容器并不是完美的,但是,deque在作为容器适配器stack和queue的底层默认的结构时却非常恰当,因为结合了vector和list的部分优势恰好满足栈和队列。所以,deque一般仅用于作为stack和queue的底层数据结构。

http://www.dtcms.com/a/463767.html

相关文章:

  • 广州做手机网站信息做包装盒效果图的网站
  • 网站建设ppt简介微信小程序开发工具教程
  • 二手书网站建设策划书邯郸百姓网免费发布信息
  • 大山子网站建设网络系统管理大赛样题
  • 网站建设详情页一般建设网站的常见问题
  • 河南网站建设优化做流量的网站
  • 网站建设电销天河网站建设集团
  • 网站seo方案设计建设网站得多少钱
  • 网站开发答辩网站认证源码
  • 咖啡网站设计建设网络服务列表在哪里
  • 自助分红网站建设安卓网站建站系统下载
  • 检察门户网站 建设意义简述网站建设和推广评价指标
  • 如何创建自己网站做网站公司青岛
  • 亚马逊在哪个网站做推广培训网站建设课程
  • html免费网站模板下载wordpress标签多重筛选
  • 福州最好的网站建设公司我的网站没备案怎么做淘宝客推广
  • MATLAB基于组合赋权云模型的危险品运输教员CBTA胜任力评价
  • 福州房地产网站建设商丘做网站公司
  • 做网站网络公司什么网站做海报赚钱
  • 上海怎么建设网站南昌网页制作公司
  • 大理高端网站建设个人网页制作完整教程
  • 外贸自建零售网站做仿牌管理咨询公司ppt
  • 网页可信站点天元建设集团有限公司第八建筑
  • 广州站电话django企业网站开发实例
  • 陕西网站建设策划内容wap游戏引擎
  • 台州市建设监理协会网站襄阳php网站开发
  • 怎样提高网站转化率重庆建设摩托车质量怎么样
  • 制作一般网站自己做网站怎么做
  • 网站做好了怎么上线网络管理是做什么的
  • 网站建设过程有哪几个阶段深圳住房和城乡建设局网站