当前位置: 首页 > article >正文

C++ STL - 容器

C++ STL(标准模板库)中的容器是一组通用的、可复用的数据结构,用于存储和管理不同类型的数据。

零. 简介


STL 容器提供了一系列预定义的类,如 vector(动态数组)、list(双向链表)、deque(双端队列)、set(集合)、map(映射)等。

意义和作用

  1. 提高编程效率:无需自己实现常见的数据结构。

  2. 代码简洁:使用统一的接口和操作方式。

  3. 灵活性:适应不同的需求和数据类型。

  4. 可扩展性:易于添加新的容器或扩展现有容器的功能。

  5. 性能优化:经过精心设计和优化。

  6. 类型安全:在编译时进行类型检查。

  7. 代码可维护性:减少重复代码,提高代码的可读性和可维护性。

例如,使用 vector 可以方便地管理动态数组,而不需要自己手动实现动态内存分配和元素添加、删除等操作。

一 . vector(动态数组)

vector 是 C++ STL 中的一种动态数组容器。它具有以下特点和优势:

  1. 动态调整大小:可以根据需要自动调整存储空间。

  2. 高效的随机访问:支持通过索引进行快速访问。

  3. 易于使用:提供了丰富的接口和操作方法。

  4. 自动内存管理:无需手动处理内存分配和释放。

有以下常用的 API:

  • push_back():在数组末尾添加元素。

  • pop_back():删除数组末尾的元素。

  • at():通过索引访问元素,提供边界检查。

  • [] 操作符:通过索引访问元素。

  • size():获取数组中元素的数量。

  • empty():判断数组是否为空。

  • begin():获取数组的起始迭代器。

  • end():获取数组的末尾迭代器。

  • clear():清空数组中的所有元素。

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

  • erase():删除指定元素或指定范围的元素。

以下是一个使用 vector 的示例代码:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> numbers;

    // 向 vector 中添加元素
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);

    // 输出 vector 中的元素
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

二. list(双向链表)

list 是 C++ STL 中的双向链表容器.

它具有以下常用的 API:

  • push_back():在链表末尾添加元素。

  • push_front():在链表开头添加元素。

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

  • erase():删除指定元素或指定范围的元素。

  • clear():清空链表中的所有元素。

  • size():获取链表中元素的数量。

  • empty():判断链表是否为空。

  • front():获取链表开头的元素。

  • back():获取链表末尾的元素。

  • begin():获取链表的起始迭代器。

  • end():获取链表的末尾迭代器。

以下是一个使用 list 的示例代码:

#include <list>
#include <iostream>

int main() {


    std::list<int> numbers;

    // 在链表末尾添加元素
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);

    // 在链表开头添加元素
    numbers.push_front(0);


    // 输出链表中的元素
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

三. deque(双端队列)

deque 是一种可以在两端高效地进行插入和删除操作的容器。
意义和作用

  1. 高效的两端操作:可以在队列的两端快速添加和删除元素。

  2. 动态调整大小:自动根据需要调整内存。

  3. 支持随机访问:像数组一样,可以通过索引访问元素。

  4. 通用数据结构:适用于多种场景。

  5. 提高代码效率和可维护性:提供了简洁、高效的接口。

例如,可以使用 deque 来实现一个队列或栈的功能。

常用 API 包括:

  • push_back():在队列尾部添加元素。

  • push_front():在队列头部添加元素。

  • pop_back():从队列尾部删除元素。

  • pop_front():从队列头部删除元素。

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

  • erase():删除指定元素或指定范围的元素。

  • clear():清空队列中的所有元素。

  • size():获取队列中元素的数量。

  • empty():判断队列是否为空。

  • begin():获取队列的起始迭代器。

  • end():获取队列的末尾迭代器。

下面是一个简单的 deque 使用示例代码:

#include <deque>
#include <iostream>

int main() {
    std::deque<int> numbers;

    numbers.push_back(1); //向最后面插入数据   1
    numbers.push_front(2);//向最钱面插入数据   2, 1
    numbers.push_back(3); //向最后面插入数据   2, 1,3
    numbers.push_front(4);//向最钱面插入数据   4, 2, 1,3

    std::cout << "Front: " << numbers.front() << std::endl;
    std::cout << "Back: " << numbers.back() << std::endl;

    return 0;
}

四. set(集合)

set 是一种无序且不允许重复元素的容器。

意义和作用

  1. 自动去重:无需手动处理重复元素。

  2. 快速查找:提供高效的元素查找操作。

  3. 无序存储:元素的顺序是随机的。

  4. 键值对操作:常用于存储键值。

常用的 API 包括:

  • insert():插入元素。

  • find():查找元素。

  • erase():删除元素。

  • size():获取元素数量。

  • empty():判断是否为空。

下面是一个简单的示例代码:

#include <set>
#include <iostream>

int main() {
    std::set<int> numbers = { 1, 2, 3, 4, 5 };
    numbers.insert(3);//插入已有数据 3
    numbers.insert(6); //插入未有数据
    //循环打印

    for (std::set<int>::iterator i = numbers.begin(); i != numbers.end(); ++i)
    {
        std::cout << *i << std::endl;
    }


    // 查找元素
    if (numbers.find(3) != numbers.end()) {
        std::cout << "Element found" << std::endl;
    }
    else {
        std::cout << "Element not found" << std::endl;
    }

    return 0;
}

五. map(映射)

map(映射)是一种关联容器,它将键(key)和值(value)进行关联。 是一种无序容器,其中键必须是唯一的。

意义和作用

  1. 提供了一种键值对的存储方式。

  2. 快速的键值查找。

  3. 自动根据键进行排序。

常用 API

  • insert():插入键值对。

  • find():根据键查找对应的值。

  • erase():删除键值对。

  • size():获取映射中键值对的数量。

  • empty():判断映射是否为空。

下面是一个简单的示例代码:

#include <map>
#include <iostream>

int main() {
    std::map<std::string, int> grades;

    grades["a"] = 1;
    grades["b"] = 2;
    grades["c"] = 3;

    // 根据键查找值
    int aliceGrade = grades["a"];

    std::cout << "a: " << aliceGrade << std::endl;

    return 0;
}

扩展:

可以用来做观察者模式;

观察者模式是一种设计模式,它定义了对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

在 C++ 中,可以使用观察者模式来实现 map 的变化通知。下面是一个简单的示例代码:

#include <iostream>
#include <map>
#include <string>
#include <vector>

class Observer {
public:
    virtual void update() = 0;
};

class Subject {
private:
    std::map<std::string, int> data;
    std::vector<Observer*> observers;

public:
    void addObserver(Observer* observer) {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) {
        auto it = std::find(observers.begin(), observers.end(), observer);
        if (it != observers.end()) {
            observers.erase(it);
        }
    }

    void updateObservers() {
        for (Observer* observer : observers) {
            observer->update();
        }
    }

    void setKeyValue(const std::string& key, int value) {
        data[key] = value;
        updateObservers();
    }

    int getValue(const std::string& key) {
        return data[key];
    }
};

class DisplayObserver1 : public Observer {
public:
    void update() override {
        std::cout << "Data changed1" << std::endl;
    }
};

class DisplayObserver2 : public Observer {
public:
    void update() override {
        std::cout << "Data changed2" << std::endl;
    }
};

int main() {
    Subject subject;

    DisplayObserver1 observer1;
    subject.addObserver(&observer1);

    DisplayObserver2 observer2;
    subject.addObserver(&observer2);

    subject.setKeyValue("key1", 10);

    return 0;
}

C++ STL(标准模板库)中的容器是一组通用的、可复用的数据结构,用于存储和管理不同类型的数据。

零. 简介


STL 容器提供了一系列预定义的类,如 vector(动态数组)、list(双向链表)、deque(双端队列)、set(集合)、map(映射)等。

意义和作用

  1. 提高编程效率:无需自己实现常见的数据结构。

  2. 代码简洁:使用统一的接口和操作方式。

  3. 灵活性:适应不同的需求和数据类型。

  4. 可扩展性:易于添加新的容器或扩展现有容器的功能。

  5. 性能优化:经过精心设计和优化。

  6. 类型安全:在编译时进行类型检查。

  7. 代码可维护性:减少重复代码,提高代码的可读性和可维护性。

例如,使用 vector 可以方便地管理动态数组,而不需要自己手动实现动态内存分配和元素添加、删除等操作。

一 . vector(动态数组)

vector 是 C++ STL 中的一种动态数组容器。它具有以下特点和优势:

  1. 动态调整大小:可以根据需要自动调整存储空间。

  2. 高效的随机访问:支持通过索引进行快速访问。

  3. 易于使用:提供了丰富的接口和操作方法。

  4. 自动内存管理:无需手动处理内存分配和释放。

有以下常用的 API:

  • push_back():在数组末尾添加元素。

  • pop_back():删除数组末尾的元素。

  • at():通过索引访问元素,提供边界检查。

  • [] 操作符:通过索引访问元素。

  • size():获取数组中元素的数量。

  • empty():判断数组是否为空。

  • begin():获取数组的起始迭代器。

  • end():获取数组的末尾迭代器。

  • clear():清空数组中的所有元素。

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

  • erase():删除指定元素或指定范围的元素。

以下是一个使用 vector 的示例代码:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> numbers;

    // 向 vector 中添加元素
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);

    // 输出 vector 中的元素
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

二. list(双向链表)

list 是 C++ STL 中的双向链表容器.

它具有以下常用的 API:

  • push_back():在链表末尾添加元素。

  • push_front():在链表开头添加元素。

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

  • erase():删除指定元素或指定范围的元素。

  • clear():清空链表中的所有元素。

  • size():获取链表中元素的数量。

  • empty():判断链表是否为空。

  • front():获取链表开头的元素。

  • back():获取链表末尾的元素。

  • begin():获取链表的起始迭代器。

  • end():获取链表的末尾迭代器。

以下是一个使用 list 的示例代码:

#include <list>
#include <iostream>

int main() {


    std::list<int> numbers;

    // 在链表末尾添加元素
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);

    // 在链表开头添加元素
    numbers.push_front(0);


    // 输出链表中的元素
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

三. deque(双端队列)

deque 是一种可以在两端高效地进行插入和删除操作的容器。
意义和作用

  1. 高效的两端操作:可以在队列的两端快速添加和删除元素。

  2. 动态调整大小:自动根据需要调整内存。

  3. 支持随机访问:像数组一样,可以通过索引访问元素。

  4. 通用数据结构:适用于多种场景。

  5. 提高代码效率和可维护性:提供了简洁、高效的接口。

例如,可以使用 deque 来实现一个队列或栈的功能。

常用 API 包括:

  • push_back():在队列尾部添加元素。

  • push_front():在队列头部添加元素。

  • pop_back():从队列尾部删除元素。

  • pop_front():从队列头部删除元素。

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

  • erase():删除指定元素或指定范围的元素。

  • clear():清空队列中的所有元素。

  • size():获取队列中元素的数量。

  • empty():判断队列是否为空。

  • begin():获取队列的起始迭代器。

  • end():获取队列的末尾迭代器。

下面是一个简单的 deque 使用示例代码:

#include <deque>
#include <iostream>

int main() {
    std::deque<int> numbers;

    numbers.push_back(1); //向最后面插入数据   1
    numbers.push_front(2);//向最钱面插入数据   2, 1
    numbers.push_back(3); //向最后面插入数据   2, 1,3
    numbers.push_front(4);//向最钱面插入数据   4, 2, 1,3

    std::cout << "Front: " << numbers.front() << std::endl;
    std::cout << "Back: " << numbers.back() << std::endl;

    return 0;
}

四. set(集合)

set 是一种无序且不允许重复元素的容器。

意义和作用

  1. 自动去重:无需手动处理重复元素。

  2. 快速查找:提供高效的元素查找操作。

  3. 无序存储:元素的顺序是随机的。

  4. 键值对操作:常用于存储键值。

常用的 API 包括:

  • insert():插入元素。

  • find():查找元素。

  • erase():删除元素。

  • size():获取元素数量。

  • empty():判断是否为空。

下面是一个简单的示例代码:

#include <set>
#include <iostream>

int main() {
    std::set<int> numbers = { 1, 2, 3, 4, 5 };
    numbers.insert(3);//插入已有数据 3
    numbers.insert(6); //插入未有数据
    //循环打印

    for (std::set<int>::iterator i = numbers.begin(); i != numbers.end(); ++i)
    {
        std::cout << *i << std::endl;
    }


    // 查找元素
    if (numbers.find(3) != numbers.end()) {
        std::cout << "Element found" << std::endl;
    }
    else {
        std::cout << "Element not found" << std::endl;
    }

    return 0;
}

五. map(映射)

map(映射)是一种关联容器,它将键(key)和值(value)进行关联。 是一种无序容器,其中键必须是唯一的。

意义和作用

  1. 提供了一种键值对的存储方式。

  2. 快速的键值查找。

  3. 自动根据键进行排序。

常用 API

  • insert():插入键值对。

  • find():根据键查找对应的值。

  • erase():删除键值对。

  • size():获取映射中键值对的数量。

  • empty():判断映射是否为空。

下面是一个简单的示例代码:

#include <map>
#include <iostream>

int main() {
    std::map<std::string, int> grades;

    grades["a"] = 1;
    grades["b"] = 2;
    grades["c"] = 3;

    // 根据键查找值
    int aliceGrade = grades["a"];

    std::cout << "a: " << aliceGrade << std::endl;

    return 0;
}

扩展:

可以用来做观察者模式;

观察者模式是一种设计模式,它定义了对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

在 C++ 中,可以使用观察者模式来实现 map 的变化通知。下面是一个简单的示例代码:

#include <iostream>
#include <map>
#include <string>
#include <vector>

class Observer {
public:
    virtual void update() = 0;
};

class Subject {
private:
    std::map<std::string, int> data;
    std::vector<Observer*> observers;

public:
    void addObserver(Observer* observer) {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) {
        auto it = std::find(observers.begin(), observers.end(), observer);
        if (it != observers.end()) {
            observers.erase(it);
        }
    }

    void updateObservers() {
        for (Observer* observer : observers) {
            observer->update();
        }
    }

    void setKeyValue(const std::string& key, int value) {
        data[key] = value;
        updateObservers();
    }

    int getValue(const std::string& key) {
        return data[key];
    }
};

class DisplayObserver1 : public Observer {
public:
    void update() override {
        std::cout << "Data changed1" << std::endl;
    }
};

class DisplayObserver2 : public Observer {
public:
    void update() override {
        std::cout << "Data changed2" << std::endl;
    }
};

int main() {
    Subject subject;

    DisplayObserver1 observer1;
    subject.addObserver(&observer1);

    DisplayObserver2 observer2;
    subject.addObserver(&observer2);

    subject.setKeyValue("key1", 10);

    return 0;
}


http://www.kler.cn/news/366960.html

相关文章:

  • C语言程序设计:现代设计方法习题笔记《chapter5》下篇
  • 基于Multisim的音频放大电路设计与仿真
  • 传输层UDP
  • 通过rancher2.7管理k8s1.24及1.24以上版本的k8s集群
  • 华为ICT题库-AI 人工智能部分
  • Docker:容器化的革命
  • Jmeter实际应用
  • hive查询语句
  • 【ROS机器人运动控制激光雷达数据获取激光雷达避障篇——C++实现】
  • Linux常用命令1
  • S-Function
  • 洛谷——P8468 [Aya Round 1 C] 文文的构造游戏(01构造问题)
  • 【Kubernets】k8s进阶-深入了解一下Label的用法
  • npm ERR! 503 Service Unavailable one of the uplinks i
  • 云轴科技ZStack信创云平台助力上海科技大学实现信创业务落地
  • 散列表:如何打造一个工业级水平的散列表?
  • 2024.10.9华为留学生笔试题解
  • C++ | Leetcode C++题解之第513题找树左下角的值
  • [Vue warn]: <transition-group> children must be keyed: <ElTag>
  • 计算机网络-CSMA/CD协议笔记及“争用期”的理解
  • Redis-05 Redis哨兵高可用架构原理与搭建
  • TiCDC 同步 SQL_MODE 相关
  • 基于SSM的BBS社区论坛系统源码
  • Linux环境下Jmeter执行压测脚本
  • 关注 dlopen(handle, mode) 中的 mode,dlsym dlclose示例
  • 学习笔记:黑马程序员JavaWeb开发教程(2024.10.26)