C++面试:向量vector和列表list介绍

目录

vector

list

list和vector的区别

[1. 底层实现:](#1. 底层实现:)

[2. 动态性和静态性:](#2. 动态性和静态性:)

[3. 内存管理:](#3. 内存管理:)

[4. 迭代器和指针:](#4. 迭代器和指针:)

[5. 访问效率:](#5. 访问效率:)

[6. 适用场景:](#6. 适用场景:)


vector

std::vector 是 C++ STL 提供的动态数组容器,提供了多种操作。以下是一些常见的 std::vector 操作,一一列举出来

初始化和基本操作

cpp 复制代码
std::vector<int> myVector;  // 初始化一个空的向量
myVector.push_back(1);     // 添加元素到向量末尾
myVector[2] = 10;          // 访问和修改向量元素
int size = myVector.size(); // 获取向量大小

插入和删除元素

cpp 复制代码
myVector.insert(myVector.begin() + 1, 4); // 插入元素到指定位置
myVector.erase(myVector.begin() + 2);    // 删除指定位置的元素
myVector.clear();                         // 清空向量

范围操作

cpp 复制代码
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination = source; // 复制整个向量
std::vector<int> subVector(source.begin() + 1, source.begin() + 4); // 复制部分向量

元素访问和遍历

cpp 复制代码
int elementAtIndex2 = myVector[2]; // 使用下标访问元素

// 使用迭代器访问元素
for (std::vector<int>::iterator it = myVector.begin(); it != myVector.end(); ++it) {
    // ...
}

// 使用范围-based for 循环
for (const auto& element : myVector) {
    // ...
}

其他常用方法

cpp 复制代码
int firstElement = myVector.front(); // 获取第一个元素
int lastElement = myVector.back();   // 获取最后一个元素
bool isEmpty = myVector.empty();     // 判断向量是否为空
myVector.resize(8);                  // 改变向量大小

移动语义和右值引用

cpp 复制代码
std::vector<std::string> source = {"apple", "orange", "banana"};
std::vector<std::string> destination(std::make_move_iterator(source.begin()), std::make_move_iterator(source.end()));

使用迭代器进行插入和删除

cpp 复制代码
std::vector<int>::iterator it = myVector.begin() + 2;
myVector.insert(it, 10);   // 在指定位置插入元素
myVector.erase(it + 3);    // 在指定位置删除元素

在特定条件下删除元素

cpp 复制代码
myVector.erase(std::remove(myVector.begin(), myVector.end(), 3), myVector.end());

使用函数对象进行元素变换

cpp 复制代码
struct Square {
    int operator()(int x) const {
        return x * x;
    }
};

std::transform(myVector.begin(), myVector.end(), myVector.begin(), Square());

使用 std::find 查找元素

cpp 复制代码
int searchElement = 5;
auto it = std::find(myVector.begin(), myVector.end(), searchElement);
if (it != myVector.end()) {
    // 元素找到的处理
}

排序向量

cpp 复制代码
std::sort(myVector.begin(), myVector.end());

反向遍历向量

cpp 复制代码
// 使用逆向迭代器
for (auto it = myVector.rbegin(); it != myVector.rend(); ++it) {
    // ...
}

查找最小和最大元素

cpp 复制代码
auto minElement = std::min_element(myVector.begin(), myVector.end());
auto maxElement = std::max_element(myVector.begin(), myVector.end());

计算向量的和

cpp 复制代码
int sum = std::accumulate(myVector.begin(), myVector.end(), 0);

使用 lambda 表达式进行元素变换

cpp 复制代码
// 将所有元素加倍
std::transform(myVector.begin(), myVector.end(), myVector.begin(), [](int x) { return x * 2; });

使用 std::copy 复制向量

cpp 复制代码
std::vector<int> copyVector;
std::copy(myVector.begin(), myVector.end(), std::back_inserter(copyVector));

将向量转为数组

cpp 复制代码
int* arrayData = myVector.data();

遍历并修改所有元素

cpp 复制代码
for (auto& element : myVector) {
    element *= 2;
}

使用自定义比较函数进行排序

cpp 复制代码
// 按照元素的绝对值进行升序排序
std::sort(myVector.begin(), myVector.end(), [](int a, int b) {
    return std::abs(a) < std::abs(b);
});

使用 std::reverse 反转向量

cpp 复制代码
std::reverse(myVector.begin(), myVector.end());

list

  1. 初始化和基本操作:
cpp 复制代码
#include <list>

std::list<int> myList;           // 初始化一个空的列表
std::list<int> myList2 = {1, 2};  // 使用初始化列表初始化列表

myList.push_back(3);              // 在列表末尾添加元素
myList.push_front(2);             // 在列表开头添加元素

int frontElement = myList.front(); // 获取列表第一个元素
int backElement = myList.back();   // 获取列表最后一个元素

myList.pop_back();                 // 删除列表末尾的元素
myList.pop_front();                // 删除列表开头的元素
  1. 插入和删除元素:
cpp 复制代码
#include <list>

std::list<int> myList = {1, 2, 3, 4};

auto it = myList.begin();
++it; // 移动到第二个元素的位置

myList.insert(it, 5);     // 在指定位置插入元素
myList.erase(it);         // 删除指定位置的元素

myList.remove(3);         // 删除列表中所有值为3的元素
myList.clear();           // 清空列表
  1. 迭代器和遍历:
cpp 复制代码
#include <list>

std::list<int> myList = {1, 2, 3, 4};

// 使用迭代器遍历列表
for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {
    // ...
}

// 使用范围-based for 循环
for (const auto& element : myList) {
    // ...
}
  1. 查找和替换:
cpp 复制代码
#include <list>
#include <algorithm>

std::list<int> myList = {1, 2, 3, 4};

auto it = std::find(myList.begin(), myList.end(), 3); // 查找元素

if (it != myList.end()) {
    // 元素找到的处理
}

myList.unique(); // 删除相邻重复元素
  1. 合并和拆分:
cpp 复制代码
#include <list>

std::list<int> myList1 = {1, 3, 5};
std::list<int> myList2 = {2, 4, 6};

myList1.merge(myList2);  // 合并两个已排序的列表

std::list<int> newList;
auto it = std::find(myList1.begin(), myList1.end(), 3);
newList.splice(newList.begin(), myList1, it, myList1.end()); // 从一个列表移动元素到另一个列表
  1. 使用自定义类型:
cpp 复制代码
#include <list>
#include <iostream>

// 自定义类型
struct Person {
    std::string name;
    int age;
};

int main() {
    // 使用自定义类型的列表
    std::list<Person> people = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 22}};

    // 访问和修改自定义类型的列表元素
    auto it = people.begin();
    it->age = 32;

    // 迭代自定义类型的列表元素
    for (const auto& person : people) {
        std::cout << person.name << " - " << person.age << " years old" << std::endl;
    }

    return 0;
}
  1. 将列表转为数组:
cpp 复制代码
#include <list>
#include <vector>

std::list<int> myList = {1, 2, 3, 4};

// 将列表转为数组
std::vector<int> myVector(myList.begin(), myList.end());

9. 自定义比较函数进行排序

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

// 自定义比较函数
bool compare(int a, int b) {
    return a > b;  // 降序排序
}

int main() {
    std::list<int> myList = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};

    // 使用自定义比较函数进行排序
    myList.sort(compare);

    // 输出排序后的列表元素
    for (const auto& element : myList) {
        std::cout << element << " ";
    }
    std::cout << std::endl;

    return 0;
}

list和vector的区别

1. 底层实现:

  • std::list 使用双向链表实现,每个元素存储下一个元素和前一个元素的地址,因此在插入和删除元素时,效率较高。但是,由于不是连续存储的,随机访问元素的性能较差。

  • std::vector 使用动态数组实现,元素在内存中是连续存储的,支持通过索引进行快速的随机访问。但在插入和删除元素时,可能需要移动其他元素,因此效率相对较低。

2. 动态性和静态性:

  • std::list 是动态容器,可以在运行时动态增加或删除元素。

  • std::vector 是静态容器,其大小在声明时就已经确定,无法动态改变。需要重新分配内存和复制元素才能改变其大小。

3. 内存管理:

  • std::list 每个元素都有独立的内存块,插入和删除元素时不需要移动其他元素,因此内存管理较为灵活。但是,由于链表结构,会带来额外的指针开销。

  • std::vector 元素在内存中是紧密排列的,随机访问效率高。但插入和删除元素可能需要移动其他元素,导致额外的开销。

4. 迭代器和指针:

std::list 提供双向迭代器,支持双向遍历。

cpp 复制代码
std::list<int>::iterator it = myList.begin();

std::vector 提供随机访问迭代器,支持快速的随机访问

cpp 复制代码
std::vector<int>::iterator it = myVector.begin();

5. 访问效率:

  • std::list 随机访问效率较低,因为需要沿着链表逐个移动。但在插入和删除元素时,std::list 的性能较好,尤其是在中间位置。

  • std::vector 允许通过索引进行快速的随机访问,因为元素在内存中是连续存储的。然而,在中间插入或删除元素时可能涉及元素的移动,效率较低。

6. 适用场景:

  • std::list 适用于频繁的插入和删除操作,以及在序列中间位置进行操作的场景。

  • std::vector 适用于需要高效随机访问的场景,以及在序列末尾进行插入和删除操作的场景。

选择使用 std::list 还是 std::vector 取决于具体的使用场景和操作需求。需要根据插入、删除、访问等操作的频率和性能要求来选择合适的容器

相关推荐
Swift社区2 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht2 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht2 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20242 小时前
Swift 数组
开发语言
南东山人3 小时前
一文说清:C和C++混合编程
c语言·c++
stm 学习ing3 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc4 小时前
《Python基础》之字符串格式化输出
开发语言·python
mqiqe5 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin5 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python