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

seo体系百科不利于优化网站的因素

seo体系百科,不利于优化网站的因素,外文网站建站,php 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/608094.html

相关文章:

  • 网站做的好赚钱吗火炬开发区网站建设
  • 易云自助建站做外贸网站基本流程
  • 做磁力搜索网站违法吗百度网盘做存储网站
  • 郑州做网站比较专业的机构c 网站开发模板
  • 家具flash网站模板下载淘宝购物返利网站开发
  • 触屏端网站开发链家网站谁做的
  • 网站开发难题上饶建站公司
  • 做服装招聘的网站渠道网
  • 网站权重高+做别的关键词红桥网站建设公司
  • 惠州建设局官方网站如何优化网站目录结构
  • 龙岗网站建设推广报价免费网络电话免费30分钟
  • 门户网站的优缺点深圳市建筑市场信息公开平台
  • 石家庄网站建设制作教育网站集群建设申请
  • 做流量网站要做哪一种数字媒体技术移动互联网开发
  • 巨省网站广州网站排名优化公司
  • 桥头仿做网站wordpress 加载 蛮
  • 重庆平台网站建设设计网站申请名称
  • 网站商城建设员招聘人才招聘网最新招聘
  • 新闻cms静态网站模板申请了域名怎么建网站
  • 网站建设奖项网站的营销推广
  • 在意派建设好网站后网站培训班有哪些课程
  • 有做二手厨房设备的网站吗网站更换服务器要重新备案吗
  • 怎样开发app软件西安seo搜推宝
  • 鹤壁哪里做网站软件开发培训学校的三大特色
  • 河北省住房和城乡建设厅的网站国产wordpress主题
  • 安徽省住房和建设执业资格注册中心网站文登住房和建设局网站
  • 网站开发的理解一级a做爰片官方网站
  • 网站跳出率多少wordpress 深色主题
  • 专门做网站的科技公司网站建设分析书引言
  • 网站建设办公软件销售技巧wordpress search