龙空技术网

C++的三大容器之顺序容器

搬砖搬知识 110

前言:

现在你们对“c升序排列函数”都比较关怀,朋友们都想要了解一些“c升序排列函数”的相关资讯。那么小编在网上收集了一些对于“c升序排列函数””的相关知识,希望大家能喜欢,姐妹们一起来学习一下吧!

顺序容器就是数据结构里的线性表,一共有 5 种:array、vector、deque、list、forward_list

如果按照存储的方式又可以分为链式存储(list 和 forward_list)和连续地址存储(array、vector 和 deque)

连续地址存储

链式存储

优点

查找效率高

插入删除效率高

缺点

插入删除效率低

查找效率低,存储成本略高

对于array和vector在内存中的数据存放与C语言完全兼容,所以对于数据的操作速度很快。这两种容器的区别在于array是不能扩容的,而vector可以动态的扩容。

#include <iostream>#include <vector>#include <array>#include <algorithm>int main(){    std::array<int, 10> arr;    std::vector<int> v;    std::for_each(        cbegin(arr), cend(arr),        [&v](const auto& i)        {            v.emplace_back(i);        });    std::cout << arr.size() << std::endl; // 10    std::cout << v.size() << std::endl; // 10    return 0;}

deque与vector的最大的区别是deque可以两头进行插入。删除的操作,vector只能在尾部进行插入和删除的操作。

#include <iostream>#include <deque>int main(){	std::deque<int> q;    q.emplace_back(1);    q.emplace_front(2);    for(auto i : q)    {        std::cout << i << " "; // 2 1    }    return 0;}

list 是双向链表,可以向前或者向后遍历,而 forward_list则是单向链表,只能向前遍历,查找效率会比list低。

#include <iostream>#include <list>#include <forward_list>int main(){	std::list<int> l;    l.emplace_back(1);    l.emplace_front(2);    l.emplace_back(3);    for(auto i : l)    {        std::cout << i << " "; // 2 1 3    }    std::cout << std::endl;    std::forward_list<int> fl;    fl.emplace_front(2);    fl.emplace_front(1);    for(auto i : fl)    {        std::cout << i << " "; // 1 2    }    std::cout << std::endl;    return 0;}

虽然vector、deque、list和forward_list都可以进行动态的扩容,但是它们的机制是完全不同的。我们先看看vector是怎么扩容的:

#include <iostream>#include <vector>struct Point{	int m_a;	int m_b;    Point (int a, int b) : m_a(a), m_b(b)    {        std::cout << "构造函数" << std::endl;    }    Point (const Point& p) : m_a(p.m_a), m_b(p.m_b)    {        std::cout << "拷贝构造" << std::endl;    }    Point (Point &&p) : m_a(p.m_a), m_b(p.m_b)    {        std::cout << "移动构造" << std::endl;    }};int main(){	std::vector<Point> v;    for (int i = 1; i <= 5; i++)    {        std::cout << "*********" << i << "***********" << std::endl;        v.emplace_back(i, i + 1);        std::cout << "v.size = " << v.size() << std::endl;    }    return 0;}

输出结果如下:

大家有没有发现,有时候会莫名其妙的调用拷贝构造函数,这是为什么呢?这是因为当 vector 的容量不够的时候,它会去寻找一块两倍大小的新内存,然后把旧元素拷贝或者移动过去,最后把新数据插入进去。这个问题之前我在工作中遇到过,所以影响特别深。我记得当时的业务中需要在vector容器中进行大量的数据插入,等数据达到一定量级的时候,接口返回时间越来越长。最后找到是这个原因导致,通过reserve接口进行所需容器的空间预估,可以减少动态扩容的调用拷贝构造的次数,从而提高程序性能。

而deque、list和forward_list相对比较简单,插入一个数据,扩容一个数据的大小。但是如果短时间有大量的数据插入,这时候一次性分配足够大的空间的vector的优势就比较明显了。所以实际开发中vector出现的记录很高。

标签: #c升序排列函数