c++顺序容器(一)

简介: c++顺序容器(一)

c++ 顺序容器概述

C++ 中的顺序容器是标准模板库(STL)的一部分,它提供了一组用于存储和管理对象序列的模板类。这些容器在内存中以线性顺序存储元素,允许快速顺序访问。顺序容器的主要类型包括:


vector:动态数组,支持快速随机访问。在向量的末尾添加或删除元素比较高效,但在中间或开头插入或删除元素可能较慢。


deque(双端队列):与 vector 类似,但设计用于在两端快速插入和删除元素。


list:双向链表,支持在任何位置快速插入和删除元素,但不支持快速随机访问。


forward_list:单向链表,与 list 类似,但仅支持向前遍历。相比 list,它使用更少的内存。


array:固定大小的数组。它提供与内置数组类似的功能,但增加了一些额外的功能,如 STL 兼容的迭代器。


string:专门用于字符的容器,提供了对字符串进行操作的丰富功能。

容器通用操作

在 C++ 中,标准模板库(STL)提供了多种容器,每种容器都支持一些通用操作。下面是这些操作的详细介绍


1. 构造和析构

构造:容器可以通过多种方式构造,如默认构造、复制构造、范围构造等。

析构:容器对象离开其作用域时,其析构函数会被自动调用,释放所有资源。

示例:std::vector 的构造
std::vector<int> vec1; // 默认构造
std::vector<int> vec2 = {1, 2, 3, 4, 5}; // 初始化列表构造
std::vector<int> vec3(vec2); // 复制构造


2. 迭代器操作

begin() 和 end():返回指向容器第一个元素和尾后元素的迭代器。

rbegin() 和 rend():返回反向迭代器。

示例:使用迭代器遍历 std::vector
for(auto it = vec2.begin(); it != vec2.end(); ++it) {
    std::cout << *it << " ";
}

3. 容量查询

empty():检查容器是否为空。

size():返回容器中元素的数目。


示例:检查 std::vector 的大小
std::cout << "Is empty: " << vec1.empty() << "\n";
std::cout << "Size: " << vec2.size() << "\n";


4. 元素访问

operator[] 或 at():用于访问元素。

front() 和 back():访问第一个和最后一个元素。


示例:访问 std::vector 的元素
std::cout << "First element: " << vec2.front() << "\n";
std::cout << "Last element: " << vec2.back() << "\n";

5. 修改操作

insert():在指定位置插入元素。

erase():删除一个或一范围的元素。

push_back() 和 pop_back():在末尾添加和移除元素。

示例:修改 std::vector
vec2.push_back(6); // 在末尾添加元素
vec2.erase(vec2.begin()); // 移除第一个元素


完整代码示例

下面是一个综合示例,综合了上述所有操作。

#include <iostream>
#include <vector>

int main() {
    // 使用初始化列表构造向量
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 输出原始向量
    std::cout << "Original vector: ";
    for(const auto& value : vec) {
        std::cout << value << " ";
    }
    std::cout << "\\n";

    // 检查向量是否为空并输出大小
    std::cout << "Is empty: " << vec.empty() << "\\n";
    std::cout << "Size: " << vec.size() << "\\n";
    
    // 输出第一个和最后一个元素
    std::cout << "First element: " << vec.front() << "\\n";
    std::cout << "Last element: " << vec.back() << "\\n";

    // 修改向量
    vec.push_back(6); // 在末尾添加元素
    vec.erase(vec.begin()); // 移除第一个元素

    // 输出修改后的向量
    std::cout << "Modified vector: ";
    for(const auto& value : vec) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}


输出:

Original vector: 1 2 3 4 5 
Is empty: 0
Size: 5
First element: 1
Last element: 5
Modified vector: 2 3 4 5 6 


  • 原始向量:打印了初始向量中的元素(1 2 3 4 5)。
  • 容器状态查询:
  • 向量非空(Is empty: 0,0 表示 false)。
  • 向量的初始大小为 5。
  • 元素访问:
  • 第一个元素是 1。
  • 最后一个元素是 5。
  • 修改向量:
  • 向量末尾添加了一个元素 6。
  • 从向量开头移除了第一个元素(原来的 1)。
  • 修改后的向量:最终,修改后的向量元素为 2 3 4 5 6。

迭代器

1. 迭代器的概念和类型

概念:迭代器是一个允许程序员在容器(如数组或STL容器)上进行遍历的对象。它类似于指针,但提供了更高层次的抽象。

类型:

  • 输入迭代器:仅用于从容器中读取数据。
  • 输出迭代器:仅用于向容器写入数据。
  • 前向迭代器:用于单向读写操作。
  • 双向迭代器:支持向前和向后遍历。
  • 随机访问迭代器:支持直接访问任意元素,类似数组。


2. 迭代器的操作

操作:

  • 解引用:通过 *iterator 访问迭代器指向的元素。
  • 自增:++iterator 移动到下一个元素。
  • 自减:对于双向迭代器,--iterator 移动到前一个元素。
  • 比较:使用 == 和 != 比较迭代器。
示例:使用迭代器遍历 std::vector
std::vector<int> vec = {1, 2, 3, 4, 5};
for(std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
    std::cout << *it << " ";
}


3. 迭代器的高级应用

应用:迭代器用于容器的许多操作,如插入、删除元素。

示例:使用迭代器进行插入和删除
vec.insert(vec.begin() + 2, 6); // 在第三个元素前插入 6
vec.erase(vec.begin()); // 删除第一个元素

4. 注意事项

注意:

  • 容器被修改时,迭代器可能失效。
  • 某些容器(如 std::list)不支持随机访问迭代器。

完整代码示例

#include <iostream>
#include <vector>

int main() {
    // 创建一个 vector
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用迭代器遍历并打印元素
    std::cout << "Original vector: ";
    for(auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\\n";

    // 使用迭代器插入元素
    vec.insert(vec.begin() + 2, 6);

    // 使用迭代器删除元素
    vec.erase(vec.begin());

    // 再次打印修改后的 vector
    std::cout << "Modified vector: ";
    for(const auto& value : vec) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}


输出:

Original vector: 1 2 3 4 5 
Modified vector: 2 3 6 4 5

容器定义和初始化

  1. std::vector

定义:std::vector 是一个动态数组,可以存储任意数量的同类型元素。

初始化:

空的 vector:std::vector vec;

初始化列表:std::vector vec = {1, 2, 3, 4, 5};

指定大小和初始值:std::vector vec(10, 0);(10个元素,每个都是0)std::list


std::list

定义:std::list 是一个双向链表,适用于频繁的插入和删除操作。

初始化:

空的 list:std::list lst;

初始化列表:std::list lst = {1, 2, 3, 4, 5};

std::map


定义:std::map 是一个基于键-值对的关联容器,每个键都是唯一的。

初始化:

空的 map:std::map mp;

初始化列表:std::map mp = {{1, "one"}, {2, "two"}};

示例代码

以下是一些容器定义和初始化的示例代码。

#include <iostream>
#include <vector>
#include <list>
#include <map>

int main() {
    // Vector 初始化
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::cout << "Vector: ";
    for(const int& i : vec) {
        std::cout << i << " ";
    }
    std::cout << "\\n";

    // List 初始化
    std::list<int> lst = {1, 2, 3, 4, 5};
    std::cout << "List: ";
    for(const int& i : lst) {
        std::cout << i << " ";
    }
    std::cout << "\\n";

    // Map 初始化
    std::map<int, std::string> mp = {{1, "one"}, {2, "two"}};
    std::cout << "Map: ";
    for(const auto& pair : mp) {
        std::cout << pair.first << "->" << pair.second << " ";
    }
    std::cout << std::endl;

    return 0;
}

解释

std::vector vec = {1, 2, 3, 4, 5};


这行代码创建了一个 std::vector,并使用初始化列表 {1, 2, 3, 4, 5} 进行初始化。

std::list lst = {1, 2, 3, 4, 5};


类似地,这行代码创建了一个 std::list 并使用同样的初始化列表。

std::map mp = {{1, "one"}, {2, "two"}};


这里创建了一个 std::map,其中每个元素都是一个键-值对。

C++ 容器赋值和 Swap

在 C++ 标准模板库(STL)中,容器支持赋值操作和 swap 函数。这些操作是容器类的基本功能,允许容器间的内容交换和赋值。以下是这些操作的详细介绍:


1. 赋值操作

赋值:容器可以使用赋值操作符(=)将一个容器的内容复制到另一个容器中。

示例:std::vector 的赋值
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2;
vec2 = vec1; // 将 vec1 的内容赋值给 vec2

2. Swap 操作

swap():swap 函数交换两个同类型容器的内容。这是一个非常高效的操作,通常只交换容器内部的指针,而不是复制整个容器的数据。


示例:使用 swap 交换 std::vector 的内容
std::vector<int> vec3 = {4, 5, 6};
vec1.swap(vec3); // 交换 vec1 和 vec3 的内容

完整代码示例

下面是一个综合示例,演示了赋值和 swap 操作。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec1 = {1, 2, 3};
    std::vector<int> vec2;
    std::vector<int> vec3 = {4, 5, 6};

    // 赋值操作
    vec2 = vec1; // 将 vec1 的内容赋值给 vec2

    // 输出赋值后的 vec2
    std::cout << "After assignment, vec2: ";
    for(const auto& value : vec2) {
        std::cout << value << " ";
    }
    std::cout << "\\n";

    // Swap 操作
    vec1.swap(vec3); // 交换 vec1 和 vec3 的内容

    // 输出 swap 后的 vec1 和 vec3
    std::cout << "After swap, vec1: ";
    for(const auto& value : vec1) {
        std::cout << value << " ";
    }
    std::cout << "\\n";

    std::cout << "After swap, vec3: ";
    for(const auto& value : vec3) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出:

After assignment, vec2: 1 2 3 
After swap, vec1: 4 5 6 
After swap, vec3: 1 2 3
  • 赋值操作:将 vec1 的内容赋值给 vec2,使得 vec2 的内容变为 1 2 3。
  • Swap 操作:交换 vec1 和 vec3 的内容,使得 vec1 的内容变为 4 5 6,而 vec3 的内容变为 1 2 3。


容器大小操作

在 C++ 标准模板库(STL)中,容器提供了多种操作来管理和查询其大小。这些操作允许你检查容器是否为空,获取容器的大小,调整容器的大小,以及在容器的末尾添加或删除元素。以下是这些操作的详细介绍:

1. 检查是否为空

empty():这个函数用于检查容器是否为空(即不包含任何元素)。

示例:检查 std::vector 是否为空
std::vector<int> vec;
bool isEmpty = vec.empty(); // 检查 vec 是否为空

2. 获取大小

size():返回容器中元素的数量。

示例:获取 std::vector 的大小
std::vector<int> vec = {1, 2, 3};
size_t size = vec.size(); // 获取 vec 的大小

3. 改变大小

resize():改变容器的大小。如果新大小大于当前大小,则在容器末尾添加元素。如果新大小小于当前大小,则从容器末尾删除元素。


示例:改变 std::vector 的大小
vec.resize(5); // 改变 vec 的大小为 5

4. 添加和删除元素

push_back():在容器末尾添加一个新元素。

pop_back():删除容器末尾的元素。

示例:在 std::vector 中添加和删除元素
vec.push_back(4); // 在 vec 末尾添加元素 4
vec.pop_back(); // 删除 vec 末尾的元素

完整代码示例

下面是一个综合示例,演示了上述所有大小操作。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3};

    // 检查是否为空
    std::cout << "Is empty: " << vec.empty() << "\\n";

    // 获取大小
    std::cout << "Size before resize: " << vec.size() << "\\n";

    // 改变大小
    vec.resize(5); // 改变 vec 的大小为 5

    // 输出改变大小后的 vec
    std::cout << "Size after resize: " << vec.size() << "\\n";
    std::cout << "Elements: ";
    for(const auto& value : vec) {
        std::cout << value << " ";
    }
    std::cout << "\\n";

    // 添加和删除元素
    vec.push_back(4); // 添加元素
    vec.pop_back(); // 删除元素

    // 输出最终的 vec
    std::cout << "Final elements: ";
    for(const auto& value : vec) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出:

Is empty: 0
Size before resize: 3
Size after resize: 5
Elements: 1 2 3 0 0 
Final elements: 1 2 3 0 0 
  • 检查是否为空:vec 不为空(Is empty: 0,0 表示 false)。
  • 获取大小:初始 vec 的大小为 3。
  • 改变大小:改变后的 vec 大小为 5,多出的位置用默认值 0 填充。
  • 添加和删除元素:添加了一个元素 4 然后又删除了,所以最终元素没有变化。

顺序容器操作

在 C++ 的标准模板库(STL)中,顺序容器如 vector、deque、list 等提供了一系列操作,使得元素的管理和访问变得灵活高效。以下是顺序容器的一些常用操作的详细介绍:


1. 访问元素

operator[] 和 at():用于访问指定位置的元素。at() 方法与 operator[] 相似,但它会检查索引是否越界。

示例:访问 std::vector 中的元素
std::vector<int> vec = {1, 2, 3};
int firstElement = vec[0]; // 使用 operator[]
int secondElement = vec.at(1); // 使用 at()

2. 前后元素访问

front() 和 back():分别返回容器中的第一个和最后一个元素的引用。


示例:访问 std::vector 的第一个和最后一个元素
int first = vec.front(); // 第一个元素
int last = vec.back(); // 最后一个元素

3. 迭代器

begin(), end(), rbegin(), rend():分别返回指向容器第一个元素、尾后元素的迭代器,以及对应的反向迭代器。

示例:遍历 std::vector
for(auto it = vec.begin(); it != vec.end(); ++it) {
    std::cout << *it << " ";
}

4. 修改容器

insert(), erase(), push_back(), pop_back(), clear():用于在容器中插入和删除元素。

示例:修改 std::vector
vec.push_back(4); // 添加元素
vec.erase(vec.begin()); // 删除第一个元素
vec.clear(); // 清空容器


5. 容器大小

size(), empty(), resize():获取容器的大小,检查是否为空,或者改变容器的大小。

示例:检查 std::vector 的大小和状态
bool isEmpty = vec.empty(); // 检查是否为空
size_t size = vec.size(); // 获取大小
vec.resize(3); // 调整大小

完整代码示例

下面是一个综合示例,展示了上述所有操作。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3};

    // 访问元素
    std::cout << "First element: " << vec[0] << ", Second element: " << vec.at(1) << "\\n";

    // 前后元素访问
    std::cout << "Front: " << vec.front() << ", Back: " << vec.back() << "\\n";

    // 遍历容器
    std::cout << "Elements: ";
    for(auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\\n";

    // 修改容器
    vec.push_back(4);
    vec.erase(vec.begin());
    vec.clear();

    // 容器大小操作
    std::cout << "Is empty: " << vec.empty() << "\\n";
    std::cout << "Size: " << vec.size() << "\\n";
    vec.resize(3);

    return 0;
}

输出:

Fir


c++顺序容器(二)https://developer.aliyun.com/article/1437162?spm=a2c6h.13262185.profile.37.5bba685cuSQkDD

目录
相关文章
|
18天前
|
C++ 容器
C++中自定义结构体或类作为关联容器的键
C++中自定义结构体或类作为关联容器的键
25 0
|
19天前
|
C++ 容器
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——AVL树
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——AVL树
22 5
|
18天前
|
存储 C++ 索引
|
2月前
|
存储 C++ 容器
开发与运维数组问题之C++标准库中提供数据容器作为数组的替代如何解决
开发与运维数组问题之C++标准库中提供数据容器作为数组的替代如何解决
40 5
|
16天前
|
安全 编译器 容器
C++STL容器和智能指针
C++STL容器和智能指针
|
18天前
|
存储 缓存 NoSQL
【C++】哈希容器
【C++】哈希容器
|
19天前
|
关系型数据库 C++ 容器
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——红黑树
22 0
|
2月前
|
安全 程序员 C++
C++一分钟之-C++中的并发容器
【7月更文挑战第17天】C++11引入并发容器,如`std::shared_mutex`、`std::atomic`和线程安全的集合,以解决多线程中的数据竞争和死锁。常见问题包括原子操作的误用、锁的不当使用和迭代器失效。避免陷阱的关键在于正确使用原子操作、一致的锁管理以及处理迭代器失效。通过示例展示了如何安全地使用这些工具来提升并发编程的安全性和效率。
27 1
|
2月前
|
存储 C++ 索引
|
2月前
|
存储 C++ 容器
下一篇
云函数