517-C++STL(vector,deque,list) た 入场券 2022-09-10 01:28 72阅读 0赞 ## STL的vector介绍 ## **vector:向量容器** **底层数据结构**:**是动态开辟的数组,每次以原来空间大小的2倍进行扩容的** **添加操作** vector<int> vec; 定义一个int类型的vector vec.push_back(20); 在末尾添加元素 时间复杂度O(1) 有可能导致容器扩容 vec.insert(it, 20); it迭代器指向的位置添加一个元素20 O(n) 有可能导致容器扩容 插入1个元素,元素后边的所有元素都要向后挪动1个位置 **扩容示意图如下:** 以原来空间大小的2倍进行扩容,开辟空间,还要把原来的对象在新的内存空间上拷贝构造新的对象,再把原来空间上的对象析构掉,然后free原来的空间。 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16] **容器中进行对象的构造和析构,内存的开辟和释放,都是通过容器的空间配置器allocator(负责内存开辟)和deallocator(负责内存释放),construct(对象构造),destroy(对象析构)** **删除操作** 删除: vec.pop_back(); 从末尾删除元素 时间复杂度是O(1) vec.erase(it); 删除it迭代器指向的元素 删除后不允许中间空着,从删除点向后的元素都得向前挪动位置 时间复杂度O(n) ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 1] **查询操作** 查询: operator[] 通过下标的随机访问vec[5] 时间复杂度O(1) iterator迭代器进行遍历 find for_each foreach =>是通过iterator来实现的 **注意**:对容器进行连续插入或者删除操作(insert/erase),一定要更新迭代器,否则第一次insert或者erase完成,迭代器就失效了 **常用方法介绍** size() 返回容器底层有效元素的个数 empty() 判断容器是否为空 reserve(20) 给vector预留空间的 只给容器底层开辟指定大小的内存空间,并不会添加新的元素 resize(20): 容器扩容用的 不仅给容器底层开辟指定大小的内存空间,还会添加新的元素 swap : 两个容器进行元素交换 ## vector代码应用 ## #include<vector> #include<iostream> using namespace std; int main() { vector<int> vec;//vector<string> vec; 0 1 2 4 8 16 32 64 //默认的vector,底层是0个,没有开辟空间 //vec.reserve(20);//叫做给vector容器预留20个元素空间,但是不开辟元素对象 //reserve函数:避免在使用vector的过程中频繁让容器做扩容操作 vec.resize(20);//叫做给vector容器预留20个元素空间,而且还开辟相应的元素对象 cout << vec.empty() << endl;//是否是空的?是空的返回1,不是空的返回0 cout << vec.size() << endl; //int() for (int i = 0; i < 20; ++i) { vec.push_back(rand() % 100 + 1); //第一次插入1个元素,0扩容到1,第二次插入1个元素,1扩充到2,然后2-4,4-8一直扩容下去 //vector效率低,扩容太频繁 } cout << vec.empty() << endl; cout << vec.size() << endl; //vector的operator[]运算符重载函数 int size = vec.size(); for (int i = 0; i < size; ++i) { cout << vec[i] << " "; } cout << endl; //把vec容器中所有的偶数全部删除 auto it2 = vec.begin(); while (it2 != vec.end()) { if (*it2 % 2 == 0) { it2 = vec.erase(it2); //删除,必须提供earse返回值给it2更新,否则会失效 } else { ++it2;//从当前迭代器指向的元素值判断,因为删除后,后面的元素前移了 } } //通过迭代器遍历vector容器 auto it1 = vec.begin(); for (; it1 != vec.end(); ++it1)//vec.end()是容器末尾元素的后继位置 { cout << *it1 << " "; } cout << endl; //给vector容器中所有的奇数前面都添加一个小于奇数1的偶数 44 45 56 57 for (it1 = vec.begin(); it1 != vec.end(); ++it1) { if (*it1 % 2 != 0) { it1 = vec.insert(it1, *it1 - 1); ++it1;//插入后,后面元素向后挪动1个位置,所以要再++一次 } } for (it1 = vec.begin(); it1 != vec.end(); ++it1) { cout << *it1 << " "; } cout << endl; return 0; } ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 2] ## STL的deque介绍 ## **deque:双端队列容器** **底层数据结构**:动态开辟的二维数组,一维数组从2开始,以2倍的方式进行扩容,每次扩容后,原来第二维的数组,从新的第一维数组的下标oldsize/2开始存放,上下都预留相同的空行,方便支持deque的首尾元素添加 ![在这里插入图片描述][63d7fefa7d0b45649748589e22c05658.png] **第一维空间大小是MAP\_SZIE=2,第二维和元素类型有关。** **如果T是int类型,则第二维空间大小是4096/4=1024个。** ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 3] **双端队列,两个端可以做队头,或者队尾。** 相当于2个方向都有2个角色。 first和last处于中间的位置(512):为了让两头都预留足够的空间,每一头都可以插入的。 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 4] 随着元素的增加,相应的指针向后或者向前跑。 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 5] 当我们元素入满的时候。 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 6] 如果还想从右向左入,这个第二维已经没有空间了。 需要进行另外一个二维的开辟。 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 7] 随着我们空间又添加满了 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 8] 此时deque就需要扩容了 **它扩容的是第一维,是按照2倍进行扩容的。** ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_14_color_FFFFFF_t_70_g_se_x_16] **然后第二维也要挪过来了。是放在第一维的中间的位置。** 因为是双端队列,任何一端都有可能进行元素的插入。给上下都预留空间。 方便元素的添加 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 9] ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 10] **然后deque又需要扩容。第一维扩容到原来的2倍。第二维挪过来,放在第一维的中间位置** ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 11] **添加元素** 前后都可以添加,不涉及其他元素的挪动 deque<int> deq; 增加: deq.push_back(20); 从末尾添加元素 O(1) deq.push_front(20); 从首部添加元素 O(1) //vec.insert(vec.begin(), 20) 时间复杂度是O(n) deq.insert(it, 20); it指向的位置添加元素 时间复杂度是O(n) **删除元素** 删除: deq.pop_back(); 从末尾删除元素 O(1) deq.pop_front(); 从首部删除元素 O(1) deq.erase(it); 从it指向的位置删除元素 时间复杂度是O(n) ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 12] **查询操作** 查询搜索: iterator(连续的insert和erase一定要考虑迭代器失效的问题) ## STL的list介绍 ## **list:链表容器 底层数据结构:双向的循环链表 pre data next** **增加元素** list<int> mylist; 增加: mylist.push_back(20); 从末尾添加元素 O(1) mylist.push_front(20); 从首部添加元素 O(1) //vec.insert(vec.begin(), 20) O(n) mylist.insert(it, 20); it指向的位置添加元素 O(1) //链表中进行insert的时候,先要进行一个query查询操作 //对于链表来说,查询操作(要遍历)效率就比较慢了 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 13] **删除元素** mylist.pop_back(); 从末尾删除元素 O(1) mylist.pop_front(); 从首部删除元素 O(1) mylist.erase(it); 从it指向的位置删除元素 O(1) **查询** 查询搜索: iterator(连续的insert和erase一定要考虑迭代器失效的问题) **deque和list,比vector容器多出来的增加删除函数接口: push\_front和pop\_front** ## vector、deque、list对比 ## **vector特点**:动态数组,内存是连续的,以2倍的方式进行扩容, vector<int> vec;//底层没有开辟任何空间 通过push_back或者insert给vector添加元素的方法: 0-1-2-4-8... 效率不高,在新的内存上用老内存的对象拷贝构造新对象,任何把老内存的对象析构,然后把老内存free reserve(20)和resize区别?在前面内容讲述过 **deque特点**:动态开辟的二维数组空间,第二维是固定长度的数组空间,扩容的时候(第一维的数组进行2倍扩容,然后把原第二维的数据存放在第一维数组的中间,支持前后的插入和删除操作,都是O(1)的操作) **问题**:deque底层内存是否是连续的? **并不是, 但是每一个第二维是连续的,所有二维之间是不连续的,因为二维是动态开辟的。** ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 14] ## vector和deque之间的区别? ## **1.底层数据结构**:不一样的。前面讲述过。 **2.前中后插入删除元素的时间复杂度**: 它们在末尾的插入和删除是一样的,时间复杂度都是 O(1) 它们在中间的插入和删除是一样的,时间复杂度都是O(n) 但是在最前面进行添加或者删除的时候, deque是O(1) vector 是O(n) **3.对于内存的使用效率**: vector 需要的内存空间必须是连续的 ,deque 可以分块进行数据存储,不需要内存空间必须是一片连续的,deque对于内存的使用效率高一些。 **4.在中间进行insert或者erase** **vector和deque它们的效率谁能好一点?** **vector好一些。** 从时间复杂度上来说,vector和deque,在中间进行insert或者erase,都要涉及数据的移动,数据量越大,移动所花费的次数和时间就多,它们的时间复杂度都是O(N),但是谁更好挪动一些? **当然是vector了**。因为vector的内存是完全连续的,不管在这里进行元素的增加还是元素的删除,其他元素在进行挪动的时候是很简单的,得益于其内存是连续的,一个个往前放,或者一个个往后放,**这样是很方便的。** ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 15] **但是如果把这个操作应用在deque中,就没有vector这么方便了。** 假设把图中打叉的元素删除掉,后面的元素就要往前挪动,但是后面的一些元素是在另一个第二维的数组上,每个第二维数组之间的内存是不连续的。这样操作指令就多了,CPU执行起来就比较费时间,比较慢了。要先访问图中靠下面的那个第二维数组的第一维的下标值,然后访问到靠上面的那个第二维数组的第一维的下标值,存储的是上面那个第二维的起始地址,然后加上偏移量,才能找到靠下面的那个第二维数组的元素应该挪到靠上面的那个第二维的数组的哪个位置上。 ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 16] ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 17] ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_15_color_FFFFFF_t_70_g_se_x_16] **容器的纵向考察**:容器掌握的深度 **容器的横向考察**:各个相似容器之间的对比 ## vector和list之间的区别? ## **vector 数组**: 在除末尾的增加删除的时间复杂度是O(n) 查询是 O(n) **但是随机访问**是O(1) (\[\]下标访问,通过CPU直接下发1个地址,就可以直接访问到了) **list 链表**: (我们要考虑搜索的时间,因为不一定就知道在哪里插入或者删除,对于链表来说,只能从头节点一个一个通过next偏移遍历,链表的搜索是O(n))**增加删除的时间复杂度是O(1)** 查询O(n) ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 18] **链表的内存不是连续的** **底层数据结构**:vector是数组 list是双向循环链表 **如果增加或者删除操作多,选择链表。如果随机访问多,选择vector** [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16]: /images/20220829/e1fe6e475d204aedbcc0708233cb2aa5.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 1]: /images/20220829/bd44ef442fc043829e481b03c14352eb.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 2]: /images/20220829/74c864cbeefc4131b17d4402f3855179.png [63d7fefa7d0b45649748589e22c05658.png]: /images/20220829/b6023c6cc7a54ac5849e5f57befe85a4.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 3]: /images/20220829/bce7ed9d24064fd28d4bf9f1ff3c592c.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 4]: /images/20220829/6c1506316916403c8cda7f88b31c7c15.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 5]: /images/20220829/1cb1aa41ce0c4e9e9453531b08b59ffc.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 6]: /images/20220829/7b65d89388d0410faf2770af4906095b.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 7]: /images/20220829/9b59c6395f9a44aaa7adebac0b24a668.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 8]: /images/20220829/787a1caee39d4d63b379cb6b4573a786.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_14_color_FFFFFF_t_70_g_se_x_16]: /images/20220829/fc9f0d1143604c93953f94555be41d79.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 9]: /images/20220829/cce26aa344164628a479d180f4cfb617.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 10]: /images/20220829/3bf572df5c314ef6abcf9a2e47a77e92.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 11]: /images/20220829/4686d1dc45f240ce95eeabbe5d369d12.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 12]: /images/20220829/df54ef85899f4d1fb0050384e34ab610.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 13]: /images/20220829/a98fa8f99f054fb1bfd68816787debec.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 14]: /images/20220829/fe51ef79144542a49ea1df995edda8b4.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 15]: /images/20220829/1d37b2739d1d4509af993fa0529c88b5.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 16]: /images/20220829/d598aac8386c4cb78f7369f1300e08bd.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 17]: /images/20220829/85ee172313994574b296dfc4ac40e7f7.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_15_color_FFFFFF_t_70_g_se_x_16]: /images/20220829/9bfe9822d414432281a3005b7d08a3b5.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBALeael-azveWuhw_size_20_color_FFFFFF_t_70_g_se_x_16 18]: /images/20220829/4428f965f14a4859afeda9e3bd2472f6.png
相关 Java实现 LeetCode 517 超级洗衣机 517. 超级洗衣机 假设有 n 台超级洗衣机放在同一排上。开始的时候,每台洗衣机内可能有一定量的衣服,也可能是空的。 在每一步操作中,你可以选择任意 m (1 ≤ m 港控/mmm°/ 2023年07月17日 15:51/ 0 赞/ 20 阅读
相关 pip安装pymssql模块时报错“PEP 517”怎么解决? 欲在ubuntu上安装pymssql,使用pip install pymssql操作,报错如下 Looking in indexes: https://pypi.tu r囧r小猫/ 2023年06月27日 05:44/ 0 赞/ 31 阅读
相关 ERROR: Could not build wheels for cryptography which use PEP 517 and cannot be installed directly 问题描述 最近在`ubuntu16.04`上安装`pwntools`卡到一个问题,报错提示如下: ERROR: Could not build wheels f 曾经终败给现在/ 2022年12月11日 06:29/ 0 赞/ 225 阅读
相关 【pip】解决ERROR: Could not build wheels for pycuda which use PEP 517 and cannot be installed directly 参考:[https://stackoverflow.com/questions/64038673/could-not-build-wheels-for-which-use-pe 蔚落/ 2022年11月18日 10:56/ 0 赞/ 560 阅读
相关 NYOJ 517 最小公倍数 (1-n 个数的最小公倍数,大数) [http://acm.nyist.net/JudgeOnline/problem.php?pid=517][http_acm.nyist.net_JudgeOnline_pr ╰+哭是因爲堅強的太久メ/ 2022年09月17日 13:23/ 0 赞/ 206 阅读
相关 ERROR: Could not build wheels for numpy which use PEP 517 and cannot be installed directly pip install pucuda 出现问题 pip install --upgrade pip setuptools wheel pip install 落日映苍穹つ/ 2022年09月13日 05:28/ 0 赞/ 139 阅读
相关 517-C++STL(vector,deque,list) STL的vector介绍 vector:向量容器 底层数据结构:是动态开辟的数组,每次以原来空间大小的2倍进行扩容的 添加操作 vector<int> v た 入场券/ 2022年09月10日 01:28/ 0 赞/ 73 阅读
相关 leetcode 517. Super Washing Machines 超级洗衣机 + 传递衣服 + 发现规律 You have n super washing machines on a line. Initially, each washing machine has some dr 本是古典 何须时尚/ 2022年06月03日 03:12/ 0 赞/ 135 阅读
相关 【LintCode 简单】517. 丑数 1.问题描述: 写一个程序来检测一个整数是不是`丑数`。 丑数的定义是,只包含质因子 `2, 3, 5` 的正整数。比如 6, 8 就是丑数,但是 14 不是丑数以为 £神魔★判官ぃ/ 2022年06月01日 05:50/ 0 赞/ 231 阅读
还没有评论,来说两句吧...