十四天学会C++之第七天:STL(标准模板库)

news2024/12/25 19:32:17

1. STL容器

  • 什么是STL容器,为什么使用它们。
  • 向量(vector):使用向量存储数据。
  • 列表(list):使用列表实现双向链表。
  • 映射(map):使用映射实现键值对存储。

什么是STL容器?

STL容器是一种用于存储和管理数据的C++模板类,它们提供了多种数据结构,以满足不同的需求。STL容器分为序列容器(Sequence Containers)和关联容器(Associative Containers)两大类。序列容器类似于数组,关联容器则基于键值对存储数据。

向量(vector)

向量是序列容器中最常用的之一,它类似于动态数组。它具有自动扩展和收缩的能力,因此可以根据需要存储任意数量的元素。

#include <vector>
#include <iostream>

int main() {
    std::vector<int> myVector;  // 创建一个整数向量

    // 向向量中添加元素
    myVector.push_back(1);
    myVector.push_back(2);
    myVector.push_back(3);

    // 遍历并输出向量中的元素
    for (int i : myVector) {
        std::cout << i << " ";
    }

    return 0;
}

列表(list)

列表是双向链表的实现,提供了高效的插入和删除操作。与向量不同,列表的元素在内存中不是连续存储的,因此适用于需要频繁插入和删除操作的情况。列表的简单示例:

#include <list>
#include <iostream>

int main() {
    std::list<std::string> myList;  // 创建一个字符串列表

    // 向列表中添加元素
    myList.push_back("Hello");
    myList.push_back("World");
    myList.push_front("C++");

    // 遍历并输出列表中的元素
    for (const std::string& str : myList) {
        std::cout << str << " ";
    }

    return 0;
}

映射(map)

映射是关联容器,它将键与值关联起来,允许通过键快速查找对应的值。这在需要构建字典、查找表或关系映射时非常有用。以下是一个映射的简单示例:

#include <map>
#include <iostream>

int main() {
    std::map<std::string, int> myMap;  // 创建一个字符串到整数的映射

    // 向映射中添加键值对
    myMap["apple"] = 5;
    myMap["banana"] = 3;
    myMap["cherry"] = 8;

    // 查找并输出映射中的值
    std::cout << "The number of bananas is: " << myMap["banana"] << std::endl;

    return 0;
}

STL容器的强大功能使它们成为C++开发中不可或缺的一部分。无论你的项目规模如何,STL都提供了各种工具,用于有效地管理和操作数据,让代码更加高效和可维护。

2. STL算法

  • 什么是STL算法,它们的作用。
  • 排序算法:介绍STL的排序算法。
  • 查找算法:介绍STL的查找算法。
  • 使用STL算法来处理容器中的数据。

什么是STL算法?

STL算法是一组通用的、可复用的算法,它们独立于特定的容器类型,可以用于处理各种数据结构。STL算法可以显著提高代码的可读性和可维护性,同时还能提供高效的性能。

排序算法

STL提供了多种排序算法,其中最常用的是std::sort()函数,它可以对容器中的元素进行升序排序。排序算法:

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> numbers = {5, 2, 8, 1, 9};

    // 使用std::sort()对向量进行升序排序
    std::sort(numbers.begin(), numbers.end());

    // 输出排序后的结果
    for (int num : numbers) {
        std::cout << num << " ";
    }

    return 0;
}

查找算法

STL还提供了多种查找算法,其中包括std::find()函数,它可以在容器中查找指定的元素。

#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> numbers = {5, 2, 8, 1, 9};
    int target = 8;

    // 使用std::find()在向量中查找目标元素
    auto result = std::find(numbers.begin(), numbers.end(), target);

    // 检查查找结果
    if (result != numbers.end()) {
        std::cout << "Found " << target << " at position " << (result - numbers.begin()) << std::endl;
    } else {
        std::cout << target << " not found." << std::endl;
    }

    return 0;
}

使用STL算法处理容器中的数据

STL算法通常以迭代器作为参数,因此它们可以应用于各种容器,如向量、列表、映射等。这使得算法非常通用和灵活。你可以使用std::for_each()std::transform()等算法来遍历容器中的元素,执行自定义的操作。

3. 自定义模板

  • 什么是模板,为什么使用模板。
  • 函数模板:创建可以处理不同数据类型的通用函数。
  • 类模板:创建可以处理不同数据类型的通用类。

什么是模板?

模板是一种通用的代码蓝图,它允许你编写可以处理不同数据类型的代码。C++中有两种主要类型的模板:函数模板和类模板。

函数模板

函数模板允许你编写通用的函数,这些函数可以接受不同类型的参数。函数模板的定义以template关键字开始,后跟模板参数列表和函数声明。

简单的函数模板,用于交换两个值:

template <typename T>
void swapValues(T &a, T &b) {
    T temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 5, y = 10;
    double a = 3.14, b = 2.71;

    swapValues(x, y);  // 交换整数
    swapValues(a, b);  // 交换双精度浮点数

    return 0;
}

函数模板的typename T部分表示模板参数,它可以是任何数据类型。

类模板

类模板允许你编写通用的类,这些类可以处理不同类型的成员变量和成员函数。类模板的定义以template关键字开始,后跟模板参数列表和类定义。

类模板,用于创建通用的栈数据结构:

template <typename T>
class Stack {
public:
    Stack() : top(-1) {}

    void push(T item) {
        if (top < MaxSize - 1) {
            data[++top] = item;
        }
    }

    T pop() {
        if (top >= 0) {
            return data[top--];
        } else {
            // 处理栈为空的情况
            throw std::runtime_error("Stack is empty");
        }
    }

private:
    static const int MaxSize = 100;
    T data[MaxSize];
    int top;
};

int main() {
    Stack<int> intStack;
    intStack.push(5);
    intStack.push(10);
    int x = intStack.pop();  // 弹出值为10的元素

    Stack<double> doubleStack;
    doubleStack.push(3.14);
    doubleStack.push(2.71);
    double y = doubleStack.pop();  // 弹出值为2.71的元素

    return 0;
}

类模板的typename T部分表示模板参数,可以是任何数据类型。

为什么使用模板?

使用模板可以使代码更加通用和灵活,无需为不同的数据类型编写重复的代码。模板还有助于提高代码的可维护性,只需编写一次通用代码,即可适用于多种数据类型。

4. 示例和练习

使用STL容器

使用STL容器的示例代码,演示向量(vector)的用法,包括添加元素、遍历容器和查找元素:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers;  // 创建整数向量

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

    // 遍历向量并输出元素
    for (int num : numbers) {
        std::cout << num << " ";
    }

    // 查找元素是否存在
    int target = 2;
    auto it = std::find(numbers.begin(), numbers.end(), target);
    if (it != numbers.end()) {
        std::cout << "\n" << target << " found at position " << std::distance(numbers.begin(), it);
    } else {
        std::cout << "\n" << target << " not found";
    }

    return 0;
}

使用STL算法

使用STL算法的示例代码,演示排序和查找算法的用法:

#include <iostream>
#include <vector>
#include <algorithm>

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

    // 排序向量
    std::sort(numbers.begin(), numbers.end());

    // 输出排序后的向量
    for (int num : numbers) {
        std::cout << num << " ";
    }

    // 使用二分查找查找元素
    int target = 5;
    if (std::binary_search(numbers.begin(), numbers.end(), target)) {
        std::cout << "\n" << target << " found";
    } else {
        std::cout << "\n" << target << " not found";
    }

    return 0;
}

使用模板

使用函数模板的示例代码,如何创建一个通用的函数来比较两个值:

#include <iostream>

template <typename T>
bool isEqual(T a, T b) {
    return a == b;
}

int main() {
    int x = 5, y = 5;
    double a = 3.14, b = 2.71;

    if (isEqual(x, y)) {
        std::cout << "x and y are equal\n";
    } else {
        std::cout << "x and y are not equal\n";
    }

    if (isEqual(a, b)) {
        std::cout << "a and b are equal\n";
    } else {
        std::cout << "a and b are not equal\n";
    }

    return 0;
}

练习题

创建一个向量,存储一组学生的分数,并计算平均分。

#include <iostream>
#include <vector>

int main() {
    std::vector<double> scores; // 创建一个双精度浮点数向量来存储学生的分数

    // 向向量添加学生分数
    scores.push_back(85.5);
    scores.push_back(92.0);
    scores.push_back(78.5);
    scores.push_back(88.0);
    scores.push_back(90.5);

    // 计算平均分
    double sum = 0.0;
    for (double score : scores) {
        sum += score;
    }
    
    double average = sum / scores.size();

    // 输出平均分
    std::cout << "平均分: " << average << std::endl;

    return 0;
}

运行结果:

在这里插入图片描述

解答:

  • 首先,包含 <iostream><vector> 头文件来使用C++的标准输入输出和向量容器。
  • 然后,创建一个std::vector<double>类型的向量,用于存储学生的分数。
  • 使用 push_back 函数将分数添加到向量中。
  • 通过迭代向量中的分数,计算它们的总和并除以向量的大小来获得平均分。
  • 最后,输出平均分。

使用STL的列表容器存储一组单词,并按字母顺序排序。

#include <iostream>
#include <list>
#include <algorithm>

int main() {
    std::list<std::string> words; // 创建一个字符串列表来存储单词

    // 向列表添加单词
    words.push_back("apple");
    words.push_back("banana");
    words.push_back("cherry");
    words.push_back("date");
    words.push_back("fig");

    // 使用STL的排序算法对单词进行排序
    words.sort();

    // 遍历并输出排序后的单词
    for (const std::string& word : words) {
        std::cout << word << " ";
    }

    return 0;
}

运行结果:

在这里插入图片描述

解答:

  • 包含了 <iostream><list> 头文件,以便使用C++的标准输入输出和列表容器。
  • 然后,创建一个 std::list<std::string> 类型的列表,用于存储单词。
  • 使用 push_back 函数将单词添加到列表中。
  • 使用 sort 函数对列表中的单词进行字母顺序排序。
  • 最后,遍历并输出排序后的单词。

创建一个通用的函数模板,用于计算两个数的最大值。

#include <iostream>

template <typename T>
T findMax(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    int intMax = findMax(42, 17);
    double doubleMax = findMax(3.14, 2.71);

    std::cout << "最大整数值: " << intMax << std::endl;
    std::cout << "最大双精度浮点数值: " << doubleMax << std::endl;

    return 0;
}

运行结果:

在这里插入图片描述

解答:

  • 定义一个通用函数模板 findMax,它可以接受任何类型的参数 ab
  • 函数模板的返回类型也是参数的类型。
  • main 函数中,演示如何使用这个模板函数来查找整数和双精度浮点数的最大值。

创建一个类模板,表示二维坐标点,包括x和y坐标。

#include <iostream>

template <typename T>
class Point {
public:
    Point(T x, T y) : x_(x), y_(y) {}

    void display() const {
        std::cout << "X坐标: " << x_ << ", Y坐标: " << y_ << std::endl;
    }

private:
    T x_;
    T y_;
};

int main() {
    Point<int> intPoint(2, 3);
    Point<double> doublePoint(1.5, 2.0);

    std::cout << "整数坐标点:" << std::endl;
    intPoint.display();

    std::cout << "双精度浮点数坐标点:" << std::endl;
    doublePoint.display();

    return 0;
}

运行结果:

在这里插入图片描述

解答:

  • 定义一个类模板 Point,它有两个模板参数 typename T,表示x和y坐标的类型。
  • 类模板有一个构造函数,可以接受两个参数,分别用于初始化x和y坐标。
  • 类模板还有一个成员函数 display,用于显示坐标点的值。
  • main 函数中,我们演示了如何创建不同类型的坐标点。

使用STL的映射容器存储学生的姓名和分数,然后按姓名查找分数。

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

int main() {
    std::map<std::string, double> studentScores; // 创建一个映射容器,姓名映射到分数

    // 向映射容器添加学生和分数
    studentScores["Alice"] = 90.5;
    studentScores["Bob"] = 88.0;
    studentScores["Charlie"] = 92.5;
    studentScores["David"] = 85.0;

    // 按姓名查找分数
    std::string nameToFind = "Bob";
    if (studentScores.find(nameToFind) != studentScores.end()) {
        double score = studentScores[nameToFind];
        std::cout << nameToFind << " 的分数是 " << score << std::endl;
    } else {
        std::cout << "找不到学生:" << nameToFind << std::endl;
    }

    return 0;
}

运行结果:

在这里插入图片描述

解答:

  • 使用 std::map 容器来创建一个学生姓名到分数的映射。
  • 使用方括号操作符 [] 添加学生和分数的映射。
  • 使用 find 函数按姓名查找分数,如果找到,就输出分数;如果找不到,就输出找不到的消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1120196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Swin Transformer V2 Scaling Up Capacity and Resolution(CVPR2022)

文章目录 AbstractIntroduction不稳定性问题下游任务需要的高分辨率问题解决内存问题- Related WorksLanguage networks and scaling upVision networks and scaling upTransferring across window / kernel resolution Swin Transformer V2Swin Transformer简介Scaling Up Mod…

使用TensorRT-LLM进行高性能推理

LLM的火爆之后&#xff0c;英伟达(NVIDIA)也发布了其相关的推理加速引擎TensorRT-LLM。TensorRT是nvidia家的一款高性能深度学习推理SDK。此SDK包含深度学习推理优化器和运行环境,可为深度学习推理应用提供低延迟和高吞吐量。而TensorRT-LLM是在TensorRT基础上针对大模型进一步…

LeetCode2409——统计共同度过的日子数

博主的解法过于冗长&#xff0c;是一直对着不同的案例debug修改出来的&#xff0c;不建议学习。虽然提交成功了&#xff0c;但是自己最后都不知道写的是啥了哈哈哈。 package keepcoding.leetcode.leetcode2409; /*Alice 和 Bob 计划分别去罗马开会。给你四个字符串 arriveA…

【每周一测】Java阶段二第四周学习

目录 1、request中的getParameter(String name)方法的功能是 2、request中的getParameter(String name)方法的功能是 3、spring创建bean对象没有以下哪个方式 4、spring依赖注入中没有以下哪个方式 5、RequestParam、RequestBody、PathVariable的应用场景及区别 6、Cooki…

第三章 网络主机扫描

本章是进入渗透测试工作流程的第一步。无论你是高级还是新手&#xff0c;本章都将帮助你成功地进行网络扫描。在开始扫描网络之前&#xff0c;我们将介绍您需要了解的基础知识。之后&#xff0c;我们将深入研究如何扫描网络目标。本章涵盖以下内容: 一、网络基础 二、识别活主…

BUUCTF 大白 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 看不到图&#xff1f; 是不是屏幕太小了 。 密文&#xff1a; 下载附件后解压&#xff0c;发现一张名为dabai.png的图片。 &#xff08;似乎因为文件被修改过&#xff0c;原图片无法放在这里&#xff0c;这张图片是…

Linux:firewalld防火墙-基础使用(2)

上一章 Linux&#xff1a;firewalld防火墙-介绍&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/133960695?spm1001.2014.3001.5501 我使用的系统为centos7 firewalld启动停止等操作 systemctl start firewalld 开启防火墙 systemct…

怎么去别人的github工程下载

1、网络 确保网络能够顺利访问github&#xff0c;有的地方的公共网络不能访问github&#xff0c;我之前开过科学上网的会员&#xff0c;发现没必要特意开去访问它。可以直接开手机热点&#xff0c;一般是可以顺利访问的。 2、下载 以我的github开源笔记qq-hh/C_review (gith…

砖家预测:腾讯云双11服务器优惠价格表(新鲜出炉)

2023腾讯云双十一服务器优惠价格表多少钱一年&#xff1f;轻量服务器2核2G3M、2核2G4M、2核4G5M、4核8G12M、8核16G18M、16核32G28M和云服务器CVM标准型S5实例优惠价格&#xff0c;腾讯云百科今年双11服务器价格会在当前的价格基础上享受个9折优惠&#xff0c;可领券 https://c…

网站技术查看

当打开一个网页感觉很好奇&#xff0c;他使用了什么框架和什么技术&#xff1f; 常用的网页技术分析网站。 1. w3techs Check web technologies used by a website - Site InfoW3Techs identifies which web technologies such as CMS, programming language, web server an…

Python中的内存管理:深入分析垃圾回收机制

python中有一个名为refchian的环状双向链表&#xff0c;python运行时创建的所有对象都会添加到refchain中。在refchain中的对象PyObject里都有一个ob_refcnt用来保存当前对象的引用计数器&#xff0c;就是该对象被引用的次数&#xff0c;当对象有新引用时ob_refcnt就会增加&…

最简单修改nacos的修改权重修改上线下线报错

前言 我在docker中部署了一个单体的nacos服务,过了一段时间,由于我导入了另外一个nacos的服务配置导致服务注册没问题,但是服务的修改权重和修改服务的上线下线会报错.于是就有了这篇文章,这篇文章主要是解决上面说的问题 正文 1.报错信息展示(这里我已经修复过了已经展示不了了…

【iOS】简单的网络请求

应iOS小组要求&#xff0c;仿写知乎日报需要实现网络请求并解析JSON格式数据&#xff0c;这篇文章仅对基本的网络请求和iOS中的JSON解析作以记录&#xff0c;还涉及到RunLoop的一点小插曲&#xff0c;具体请求过程和原理以后会详细学习&#xff01;&#x1f64f; 基本网络流程简…

42915-2023 铜精矿及主要含铜物料鉴别规范

1 范围 本文件规定了铜精矿及主要含铜物料的鉴别特征、鉴别流程、鉴别实施及鉴别报告编写。 本文件适用于进口铜精矿与主要含铜物料的鉴别&#xff0c;主要含铜物料包括冰铜、铜火法冶炼渣、铜火法 冶炼烟尘、铜阳极泥、铜渣精矿等铜火法冶炼工艺产生的物料。 2 规范性引用…

前端Vue框架系列—— 学习笔记总结Day02

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

VMwarePlayer安装Ubuntu,切换中文并安装中文输入法

1.下载和安装 虚拟机使用的免费版官网链接&#xff1a;VMwarePlayer Ubuntu镜像下载官网链接&#xff1a;Ubuntu桌面版 自己学习使用&#xff0c;不需要考虑迁移之类的。选择单个磁盘IO性能会更高 安装过程中如果出现如下报错&#xff0c;则用系统管理员身份运行 右击VMwa…

造车先做三蹦子220101--机器学习字符(字母、和数字识别)的“小白鼠”与“果蝇”

“0”数字字符零 的图片(16*16点阵)&#xff1a; import torch import torch.nn as nn import torch.optim as optim from PIL import Image, ImageDraw, ImageFont from torchvision import transforms import matplotlib.pyplot as pltTimes20001000# 参数设置 font_path &q…

嵌入式实时操作系统的设计与开发(内存资源池存储管理)

内存资源池存储管理 内存资源池存储管理属于固定大小内存管理系统&#xff0c;内存池中内存块的分配和回收是基于第一级内存管理系统的&#xff0c;因为内存池中内存块是由第一级内存管理的算法所确定的。 内存池存储管理系统主要用于操作系统的一些常用结构的内存管理。例如…

位操作符^以及正负数在计算机中的存储

(数据是怎么在计算机中存储的)​ 正数和负数在内存中都是以补码的形式存储的&#xff0c;但不同的是正数的原码&#xff0c;补码&#xff0c;反码都是相同的&#xff0c;而负数的原码&#xff0c;补码和反码是不同的。 负数的原码&#xff0c;补码&#xff0c;反码之间存在什么…

神仙级价格:腾讯云双十一服务器优惠价格表来了

2023腾讯云双十一服务器优惠价格表多少钱一年&#xff1f;轻量服务器2核2G3M、2核2G4M、2核4G5M、4核8G12M、8核16G18M、16核32G28M和云服务器CVM标准型S5实例优惠价格&#xff0c;腾讯云百科今年双11服务器价格会在当前的价格基础上享受个9折优惠&#xff0c;可领券 https://c…