list和vector容器的插入与访问操作区别

这篇具有很好参考价值的文章主要介绍了list和vector容器的插入与访问操作区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

std::liststd::vector是C++中的两种常见数据结构,它们在不同的使用场景下各有优势。

  • std::vector的内部实现是动态数组,它在连续的内存块中存储数据。这使得std::vector访问元素时具有非常高的效率,因为可以直接通过索引来访问元素,时间复杂度为O(1)。然而,std::vector在插入和删除元素时可能需要移动大量的元素,特别是在非尾部进行插入或删除操作时,时间复杂度为O(n)
  • std::list的内部实现是双向链表,它在非连续的内存块中存储数据。这使得std::list插入和删除元素时具有非常高的效率,因为你只需要修改相关节点的指针,无需移动其他元素时间复杂度为O(1)。然而,std::list在访问元素时可能需要遍历整个链表,时间复杂度为O(n)

如果主要的操作是插入元素insert操作,那么使用std::list会比使用std::vector更高效。

list插入元素和vector插入元素对比案例

leetcode406.根据身高重建队列

vector的做法

class Solution {
public:
    //注意cmp接收的是两个一维数组,而不是二维数组
    static bool cmp(vector<int>& P1,vector<int>& P2){
        if(P1[0]>P2[0])  return true;//整体降序
        if(P1[0]==P2[0]){
            if(P1[1]<P2[1]) 
                return true;//p1[0]相同的时候按照p1[1]升序
        }
        return false;
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        //先对所有的hi降序排序,因为本题的people中的变量是{a,b},所以需要自定义sort cmp
        sort(people.begin(),people.end(),cmp);
        //定义新的二维数组作为输出
        vector<vector<int>>result;
        //开始遍历排序后的people
        for(int i=0;i<people.size();i++){
            //因为此时已经排序完毕,所以[6,1]直接插入到下标为1的地方,[5,0]直接插入下标为0的地方
            int position=people[i][1];//people[i][1]就代表着第i个集合people的第二个元素!
            //元素放到对应的二维结果数组里
            result.insert(result.begin()+position,people[i]);
        }
        return result;

    }
};

list和vector容器的插入与访问操作区别,CPP语法、容器相关与易错点记录,list,数据结构,leetcode,c++

list优化的做法

class Solution {
public:
    static bool cmp(vector<int>& P1,vector<int>& P2){
        if(P1[0]>P2[0])  return true;
        if(P1[0]==P2[0]){
            if(P1[1]<P2[1]) 
                return true;
        }
        return false;
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(),people.end(),cmp);
        //结果数组类型修改为list<vector<int>>
        list<vector<int>>result;
        
        //遍历排序后的people
        for(int i=0;i<people.size();i++){
            int position=people[i][1];
            //找到position位置之后,定义迭代器再插入
            list<vector<int>>::iterator it = result.begin();
            //注意这里insert的写法,先寻找插入位置
            while(position--){
                it++;
            }
            //while结束之后找到插入位置
            result.insert(it,people[i]);
        }
        //把结果转换为vector<vector<int>>,相当于构造新的二维vector
        return vector<vector<int>>(result.begin(),result.end());

    }
};

list和vector容器的插入与访问操作区别,CPP语法、容器相关与易错点记录,list,数据结构,leetcode,c++
其直观上来看数组的insert操作是O(n)的,整体代码的时间复杂度是O(n^2)。
链表的insert查找+插入也是O(n),整体代码时间复杂度是一样的。

为什么时间复杂度相同还会有性能差异

对于普通数组,一旦定义了大小就不能改变,例如int a[10];,这个数组a至多只能放10个元素,改不了的。

对于动态数组,就是可以不用关心初始时候的大小,可以随意往里放数据,那么耗时的原因就在于动态数组的底层实现

那么动态数组为什么可以不受初始大小的限制,可以随意push_back数据呢?

首先vector的底层实现也是普通数组

vector的大小有两个维度一个是size一个是capicity,size就是我们平时用来遍历vector时候用的,例如:

for (int i = 0; i < vec.size(); i++) {

}

capicity是vector底层数组(就是普通数组)的大小,capicity不一定=size

当insert数据的时候,如果已经大于capicity,capicity会成倍扩容,但对外暴漏的size其实仅仅是+1

那么既然vector底层实现是普通数组,怎么扩容的?

就是重新申请一个二倍于原数组大小的数组,然后把数据都拷贝过去,并释放原数组内存

举一个例子,如图:
list和vector容器的插入与访问操作区别,CPP语法、容器相关与易错点记录,list,数据结构,leetcode,c++
原vector中的size和capicity相同都是3,初始化为1 2 3,此时要push_back一个元素4。

那么底层其实就要申请一个大小为6的普通数组,并且把原元素拷贝过去,释放原数组内存,注意图中底层数组的内存起始地址已经变了。

同时也注意此时capicity和size的变化,是成倍改变的!

而在本案例中,我们使用vector来做insert的操作,此时大家可会发现,虽然表面上复杂度是O(n2),但是,其底层都不知道额外做了多少次全量拷贝了,所以算上vector的底层拷贝,整体时间复杂度可以认为是O(n^2 + t × n)级别的,t是底层拷贝的次数

所以,虽然插入操作的理论时间复杂度没有改变,但 在实践中,由于std::list不需要移动元素,所以实际运行时间会更短。这就是为什么使用std::list后代码运行时间减少的原因。

参考:
代码随想录-vector和list差别解释文章来源地址https://www.toymoban.com/news/detail-535533.html

到了这里,关于list和vector容器的插入与访问操作区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++STL——list容器及其常用操作(详解)

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态

    2024年02月14日
    浏览(29)
  • 【c++】 list容器的基本操作与接口

    List容器是一个双向链表。 采用动态存储分配,不会造成内存浪费和溢出 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素 链表灵活,但是空间和时间额外耗费较大 list构造函数 list数据元素插入和删除操作 list大小操作 list赋值操作 l ist数据的存取 li

    2024年02月17日
    浏览(37)
  • C++ string类(2)—成员访问、插入、删除、替换、查找和交换操作

    目录 一、成员访问 1、operator[ ]at 2、front( )back( ) 二、插入元素 insert( ) 三、删除元素 erase( ) 四、替换元素 replace( ) 五、查找元素 find( ) 六、交换字符串 swap( ) 七、C风格 c_str 八、rfindsubstr 虽然二者功能一样,但[ ]比较常用。 访问越界[ ]会直接报错,.at( )会抛异常。 insert/er

    2024年02月05日
    浏览(29)
  • Docker - 基本概念、与虚拟机的区别、架构、镜像操作、容器操作、数据卷挂载

    目录 一、对 Docker  的理解 1、Docker 基本概念 2、Docker 与 虚拟机的区别 3、何为镜像和容器? 4、Docker 主要架构 二、Docker 基本操作 1、Docker 镜像操作 2、案例(镜像):去 DockerHub 搜索并拉取一个 Nginx 镜像,打包后删除镜像,重新加载 .tar 文件 3、Docker 容器操作 1.docker run(启

    2024年04月13日
    浏览(34)
  • CPP语法(六)——函数模板

    模板是c++的高级特性,分为函数模板和类模板。标准模板库(STL) 模板只作用于其下方的类或函数 1.1 函数模板 函数模板定义 template 为,表示定义一个模板,尖括号表示模板参数。 模板参数主要有两种:一种是模板类型参数,另一种是模板非类型参数。 1.2 重载函数模板

    2024年04月26日
    浏览(35)
  • Cpp学习——list的模拟实现

      目录 一,实现list所需要包含的三个类 二,三个类的实现 1.list_node 2.list类  3.iterator_list类 三,功能实现 1.list类里的push_back()   2.iterator类里的运算符重载 3,list类里面的功能函数 1.insert() 2.erase()函数 3.clear()与析构函数 4.拷贝构造函数赋值运算符重载 5.打印函数      因

    2024年02月12日
    浏览(29)
  • 【List】List集合有序测试案例:ArrayList,LinkedList,Vector(123)

    List是有序、可重复的容器。 有序: List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问 元素,从而精确控制这些元素。 可重复: List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器。 List接口常用的实现类有3个:

    2024年02月11日
    浏览(37)
  • Vector<T> 动态数组(模板语法)

    C++数据结构与算法 目录 1 C++自学精简教程 目录(必读) 2 动态数组 Vector(难度1) 其中,2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。 1 学会写基本的C++类模板语法; 2 为以后熟练使用 STL 打下基础; 3 为更进一步的阅读和掌握更多的C++库打下基础; 模板语

    2024年02月10日
    浏览(30)
  • 哈希表HashMap(基于vector和list)

    C++数据结构与算法实现(目录) 1 什么是HashMap? 我们这里要实现的HashMap接口不会超过标准库的版本(是一个子集)。 HashMap是一种键值对容器( 关联容器 ),又叫 字典 。 和其他容易一样,它可以对存储的元素进行 增删改查 操作。 它之所以叫关联容器,是因为它的每个元

    2024年02月10日
    浏览(29)
  • C++面试:向量vector和列表list介绍

    目录 vector list  list和vector的区别 1. 底层实现: 2. 动态性和静态性: 3. 内存管理: 4. 迭代器和指针: 5. 访问效率: 6. 适用场景:   std::vector 是 C++ STL 提供的动态数组容器,提供了多种操作。以下是一些常见的 std::vector 操作,一一列举出来 初始化和基本操作 插入和删除元

    2024年01月22日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包