【c++】列表的增删改查

常见的列表容器及其特点

C++ 标准库提供了多种容器,用于不同的需求和使用场景。以下是一些常见的列表容器及其特点:

  1. std::vector 特点:动态数组,元素存储在连续的内存块中。 访问时间:随机访问时间为常数时间 (O(1))。 插入/删除时间:末尾插入/删除为常数时间 (O(1));中间插入/删除为线性时间 (O(n))。
  2. std::list 特点:双向链表,每个元素包含指向前一个和后一个元素的指针。 访问时间:随机访问时间为线性时间 (O(n))。 插入/删除时间:在任意位置插入/删除为常数时间 (O(1))。
  3. std::forward_list 特点:单向链表,每个元素只包含指向下一个元素的指针。 访问时间:随机访问时间为线性时间 (O(n))。 插入/删除时间:在头部插入/删除为常数时间 (O(1));在中间或末尾插入/删除需要遍历链表。
  4. std::deque 特点:双端队列,支持高效地在两端进行插入和删除操作。 访问时间:随机访问时间为常数时间 (O(1))。 插入/删除时间:在两端插入/删除为常数时间 (O(1)),在中间插入/删除为线性时间 (O(n))。
  5. std::array 特点:固定大小的数组,元素存储在连续的内存块中。 访问时间:随机访问时间为常数时间 (O(1))。 插入/删除时间:不支持动态插入/删除操作,因为大小是固定的。
  6. std::string 特点:专门用于存储字符序列的动态数组。 访问时间:随机访问时间为常数时间 (O(1))。 插入/删除时间:类似于 std::vector,末尾插入/删除为常数时间 (O(1)),中间插入/删除为线性时间 (O(n))。 总结
    连续存储:std::vector, std::array, std::string(随机访问高效,插入/删除中间元素较慢)。
    链表存储:std::list, std::forward_list(随机访问较慢,插入/删除任意位置高效)。
    双端队列:std::deque(随机访问高效,两端插入/删除高效)。
    选择合适的容器需要根据具体的应用场景和操作需求来决定。例如,如果需要频繁的随机访问,可以考虑使用 std::vector 或
    std::array;如果需要高效地在中间插入和删除元素,可以考虑使用 std::list

std::vector 和 std::list

std::vector 和 std::list 是 C++ 标准库中常用的两个容器,它们在内存布局和访问方式上有显著的区别,这导致了它们在不同操作上的性能差异。

  • 内存布局
    std::vector:使用连续的内存块来存储元素。这意味着所有元素都在一个连续的内存区域中
    std::list:使用双向链表存储元素。每个元素存储在独立的内存块中,并且每个元素都有指向前一个和后一个元素的指针
  • 访问效率
    std::vector:
    由于元素存储在连续的内存块中,std::vector 支持常数时间 (O(1)) 随机访问 。例如,访问第 i 个元素可以通过 v[i] 或 *(v.data() + i) 快速实现。 连续的内存布局还利于 CPU 缓存优化。当访问 std::vector 中的元素时,CPU 可以更有效地预取数据,从而减少缓存未命中的次数,提高访问速度。
    std::list:
    std::list 不支持随机访问,因为它是通过链表结构存储的。要访问第 i 个元素,需要从头开始遍历链表,访问时间是线性时间(O(n))。 链表中的元素分散在内存的不同位置,导致访问时可能会频繁发生缓存未命中,因为每次访问下一个元素时,都需要读取新的内存地址。
  • 插入和删除效率
    std::vector:
    在末尾插入或删除元素是常数时间 (O(1)) 操作。 在中间插入或删除元素需要移动后续元素,因此是线性时间 (O(n)) 操作。
    std::list:
    在任何位置插入或删除元素都是常数时间 (O(1)) 操作,只需调整指针即可。

总结

访问效率:std::vector 的访问效率远高于 std::list,因为它支持常数时间的随机访问,并且其连续内存布局更有利于 CPU

缓存。 插入和删除效率:std::list 对于在中间任意位置的插入和删除操作更加高效,因为不需要移动其他元素。

因此,如果你的应用场景主要涉及频繁的随机访问,那么 std::vector

是更好的选择。如果主要涉及频繁的插入和删除操作,特别是在中间位置,那么 std::list

可能会表现得更好。选择合适的容器需要根据具体的使用场景和操作类型来决定。

列表容器的增删改查操作

cpp 复制代码
#include <iostream>
#include <list>

int main() {
    std::list<int> myList;

    // 增加元素 (在列表末尾添加元素)
    myList.push_back(10);
    myList.push_back(20);
    myList.push_back(30);

    // 在列表头部添加元素
    myList.push_front(5);

    std::cout << "列表内容: ";
    for (int n : myList) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    // 删除元素
    // 删除特定元素
    myList.remove(20);

    // 删除头部和尾部元素
    myList.pop_front();
    myList.pop_back();

    std::cout << "删除后的列表内容: ";
    for (int n : myList) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    // 修改元素 (将第一个找到的某个值修改为新值)
    // begin() 是 std::list<int> 类的成员函数。它返回一个迭代器,该迭代器指向列表的第一个元素。
    // myList.begin() 返回的迭代器赋值给迭代器变量 it。这意味着 it 现在指向 myList 容器中的第一个元素。
    for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {
        if (*it == 10) {
            *it = 15;
        }
    }

    std::cout << "修改后的列表内容: ";
    for (int n : myList) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    // 查找元素
    std::list<int>::iterator it = std::find(myList.begin(), myList.end(), 15);
    if (it != myList.end()) {
        std::cout << "找到了元素 15" << std::endl;
    } else {
        std::cout << "没有找到元素 15" << std::endl;
    }

    return 0;
}
详细解释:
增加元素:

push_back(value):在列表的末尾添加元素。
push_front(value):在列表的头部添加元素。
删除元素:

remove(value):删除所有匹配的元素。
pop_front():删除列表头部的元素。
pop_back():删除列表尾部的元素。
修改元素:

通过迭代器遍历列表,找到需要修改的元素,然后直接修改其值。
查找元素:

使用标准库算法 std::find 查找元素,返回指向该元素的迭代器,如果没找到则返回 end 迭代器。
这个例子展示了基本的增删改查操作。如果你需要更高效地随机访问,可以考虑使用 std::vector,但在频繁的插入和删除操作中,std::list 的性能会更好。
相关推荐
学习前端的小z3 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
神仙别闹10 分钟前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE11 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
我们的五年21 分钟前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
zwjapple28 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five29 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
前端每日三省31 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
凡人的AI工具箱44 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
做人不要太理性1 小时前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.1 小时前
2、桥接模式
c++·桥接模式