从零开始的C++编程之旅——第六篇:数组与字符串——批量数据的存储与处理

前言:从单个数据到批量数据

你好!欢迎回来。在前五篇中,我们学习了C++的核心基础:变量与数据类型、运算符、选择结构、循环结构。现在,你已经能够编写出包含复杂逻辑的程序了。但是,你会发现一个明显的限制:我们之前处理的数据都是单个的变量------一个整数、一个浮点数、一个字符。如果我们要处理成百上千个数据呢?比如一个班级50名学生的成绩、一个字符串中的每一个字符、一个图像中的每一个像素......难道要定义50个独立的变量吗?那显然不现实。

数组 正是为了解决这个问题而生的。它允许我们存储一组相同类型的数据,并通过索引来访问它们。而字符串则是字符的序列,是处理文本信息的基础。

在这一篇中,我们将深入学习:

  • 数组的声明、初始化与访问

  • 多维数组(尤其是二维数组)

  • C风格字符串(C-style strings)

  • std::string------现代C++的字符串处理方式

  • 字符串的常用操作

  • 数组与循环的完美配合

掌握这些内容后,你将能够编写出处理批量数据和文本信息的程序,这是迈向实用编程的重要一步。

第一章:数组------批量数据的容器

1.1 什么是数组?

数组是一组具有相同数据类型的元素的集合,这些元素在内存中连续存储,并通过一个共同的名称和下标(索引)来访问。

想象一下,你有一栋公寓楼,每个房间都有一个门牌号(索引),你可以通过门牌号找到对应的住户。数组也是类似的:每个元素都有一个编号(索引),从0开始。

1.2 数组的声明

声明数组需要指定三个要素:

  • 元素的数据类型

  • 数组的名称

  • 数组的大小(元素个数)

基本语法:

cpp

复制代码
数据类型 数组名[数组大小];

示例

cpp

复制代码
int scores[10];       // 声明一个包含10个整数的数组,索引0~9
double prices[5];     // 声明一个包含5个双精度浮点数的数组
char vowels[5];       // 声明一个包含5个字符的数组

注意:数组大小必须是编译期常量(C++11及以后可以使用变量作为大小,这是变长数组(VLA),但并非标准C++,不建议依赖)。在标准C++中,数组大小必须是常量表达式。

cpp

复制代码
const int SIZE = 100;
int data[SIZE];       // 正确,SIZE是常量
int n;
std::cin >> n;
int arr[n];           // 某些编译器支持,但不是标准C++!避免使用

对于需要动态大小的数组,我们后续会学习std::vector

1.3 数组的初始化

数组可以在声明时进行初始化。

1. 完全初始化

cpp

复制代码
int scores[5] = {90, 85, 78, 92, 88};

2. 部分初始化:未显式初始化的元素会被自动初始化为0(对于基本类型)。

cpp

复制代码
int scores[5] = {90, 85};   // 等价于 {90, 85, 0, 0, 0}

3. 省略大小:如果提供了初始化列表,可以省略数组大小,编译器会自动计算。

cpp

复制代码
int scores[] = {90, 85, 78, 92, 88};   // 大小为5

4. 统一初始化(C++11)

cpp

复制代码
int scores[5] {90, 85, 78, 92, 88};

5. 将所有元素初始化为0

cpp

复制代码
int scores[5] = {0};   // 所有元素为0
int scores[5] {};      // C++11起,所有元素为0

1.4 访问数组元素

数组元素通过下标运算符 []来访问。下标从0开始,到大小-1结束。

cpp

复制代码
int scores[5] = {90, 85, 78, 92, 88};
std::cout << scores[0] << std::endl;   // 输出第一个元素:90
std::cout << scores[2] << std::endl;   // 输出第三个元素:78
scores[3] = 95;                         // 修改第四个元素的值

1.5 数组的遍历

数组与循环是天作之合。通过循环变量作为下标,可以轻松遍历数组的所有元素。

cpp

复制代码
#include <iostream>

int main() {
    int scores[5] = {90, 85, 78, 92, 88};
    
    // 使用for循环遍历
    for (int i = 0; i < 5; i++) {
        std::cout << "scores[" << i << "] = " << scores[i] << std::endl;
    }
    
    return 0;
}

1.6 数组的边界

数组的索引必须在有效范围内(0 到 size-1)。访问越界(如scores[5])是未定义行为,可能导致程序崩溃、数据损坏,或看似正常运行但隐藏bug。C++不进行自动边界检查,程序员必须自己保证索引有效。

cpp

复制代码
int arr[3] = {1, 2, 3};
arr[3] = 4;   // 越界!危险!

最佳实践:使用常量表示数组大小,避免硬编码数字。

cpp

复制代码
const int SIZE = 5;
int arr[SIZE];
for (int i = 0; i < SIZE; i++) {
    // ...
}

1.7 数组的sizeof操作

sizeof运算符可以获取数组占用的总字节数,以及单个元素的大小。

cpp

复制代码
int scores[10];
std::cout << "数组总字节数: " << sizeof(scores) << std::endl;     // 40 (int占4字节)
std::cout << "元素个数: " << sizeof(scores) / sizeof(scores[0]) << std::endl;  // 10

这种技巧常用于获取数组长度,但仅适用于数组本身,不适用于指针(后面会讲)。

第二章:多维数组------表格数据

2.1 二维数组的概念

一维数组可以看作一行数据,而二维数组可以看作一张表格(行和列)。声明二维数组的语法:

cpp

复制代码
数据类型 数组名[行数][列数];

例如,一个3行4列的整数矩阵:

cpp

复制代码
int matrix[3][4];

逻辑上可以想象为:

text

复制代码
matrix[0][0] matrix[0][1] matrix[0][2] matrix[0][3]
matrix[1][0] matrix[1][1] matrix[1][2] matrix[1][3]
matrix[2][0] matrix[2][1] matrix[2][2] matrix[2][3]

实际上,C++中的二维数组在内存中是按行连续存储的(行优先)。

2.2 二维数组的初始化

1. 嵌套花括号初始化

cpp

复制代码
int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

2. 省略内层花括号(按行顺序填充)

cpp

复制代码
int matrix[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

3. 部分初始化(未指定的元素自动为0)

cpp

复制代码
int matrix[3][4] = {
    {1, 2},          // 第一行前两个为1,2,后两个为0
    {5, 6, 7}        // 第二行前三为5,6,7,最后一列为0
};                   // 第三行全0

4. 省略第一维大小(第二维必须指定)

cpp

复制代码
int matrix[][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8}
};   // 编译器自动推断第一维大小为2

2.3 二维数组的访问与遍历

使用两个下标访问元素。通常使用嵌套循环遍历。

cpp

复制代码
#include <iostream>

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 输出矩阵
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            std::cout << matrix[i][j] << "\t";
        }
        std::cout << std::endl;
    }
    
    return 0;
}

2.4 二维数组的常见应用

  • 矩阵运算:加法、乘法、转置等

  • 游戏地图:用二维数组表示棋盘、网格世界

  • 图像处理:像素的灰度值或RGB值

  • 学生成绩表:行表示学生,列表示科目

第三章:C风格字符串------字符数组

在C++中,除了后面要讲的std::string,还有一种源自C语言的字符串表示方式:C风格字符串 。它本质上是一个字符数组,以空字符'\0'(ASCII码0)作为结束标志。

3.1 声明与初始化

cpp

复制代码
char str1[6] = {'H', 'e', 'l', 'l', 'o', '\0'};  // 显式添加结束符
char str2[6] = "Hello";                           // 字符串字面量自动添加'\0'
char str3[] = "Hello";                            // 大小自动为6(包含'\0')

注意:字符串字面量"Hello"实际占用6个字符(H,e,l,l,o,\0)。所以数组大小必须至少比字符个数多1。

3.2 输入与输出

cpp

复制代码
char name[50];
std::cout << "请输入你的名字:";
std::cin >> name;      // 读取一个单词(以空白符分隔)
std::cout << "你好," << name << std::endl;

std::cin >> name会读取直到空白符,且不会检查缓冲区大小,可能导致缓冲区溢出。更安全的方法是使用std::cin.getline()

cpp

复制代码
char name[50];
std::cin.getline(name, 50);   // 读取一行,最多49个字符+'\0'

3.3 常用C字符串函数

C++继承了C标准库中的字符串处理函数,需要包含<cstring>头文件。

函数 功能 示例
strlen(str) 返回字符串长度(不含'\0') int len = strlen("Hello"); // 5
strcpy(dest, src) 复制字符串 strcpy(dest, src);
strncpy(dest, src, n) 复制最多n个字符 strncpy(dest, src, 10);
strcat(dest, src) 拼接字符串 strcat(dest, src);
strcmp(str1, str2) 比较字符串(返回0表示相等) if (strcmp(s1, s2) == 0)
strchr(str, ch) 查找字符第一次出现的位置 char *p = strchr(str, 'a');
strstr(str, substr) 查找子串第一次出现的位置 char *p = strstr(str, "abc");

示例

cpp

复制代码
#include <iostream>
#include <cstring>

int main() {
    char s1[20] = "Hello";
    char s2[20] = "World";
    
    std::cout << "长度: " << strlen(s1) << std::endl;     // 5
    
    strcat(s1, " ");     // 拼接空格
    strcat(s1, s2);      // 拼接s2
    std::cout << s1 << std::endl;   // "Hello World"
    
    if (strcmp(s1, "Hello World") == 0) {
        std::cout << "相等" << std::endl;
    }
    
    return 0;
}

3.4 C风格字符串的缺点

  • 不安全:容易缓冲区溢出

  • 繁琐:需要手动管理内存和结束符

  • 功能有限 :相比std::string,操作复杂

因此,在现代C++编程中,除非有特殊原因(如与C代码交互),强烈推荐使用std::string

第四章:std::string------现代C++字符串

std::string是C++标准库提供的字符串类,位于<string>头文件中。它封装了字符数组,提供了丰富的成员函数,使用起来安全、便捷。

4.1 基本使用

cpp

复制代码
#include <iostream>
#include <string>

int main() {
    std::string s1;                  // 空字符串
    std::string s2 = "Hello";        // 初始化为"Hello"
    std::string s3("World");         // 另一种初始化
    std::string s4 = s2;             // 拷贝构造
    std::string s5(5, 'A');          // "AAAAA"
    
    std::cout << s2 << " " << s3 << std::endl;
    
    return 0;
}

4.2 输入与输出

cpp

复制代码
std::string name;
std::cout << "请输入你的名字:";
std::cin >> name;               // 读取一个单词
std::cout << "你好," << name << std::endl;

// 读取整行(包括空格)
std::string line;
std::getline(std::cin, line);

4.3 字符串拼接

使用++=运算符非常方便。

cpp

复制代码
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = s1 + " " + s2;   // "Hello World"
s1 += " C++";                     // s1变为"Hello C++"

4.4 访问字符

可以使用[]运算符或at()成员函数访问单个字符。at()会进行边界检查,越界时抛出异常,更安全。

cpp

复制代码
std::string s = "Hello";
char ch1 = s[0];        // 'H'
char ch2 = s.at(1);     // 'e'
s[0] = 'h';             // 修改为"hello"

4.5 字符串长度

cpp

复制代码
std::string s = "Hello";
int len = s.length();    // 5
int size = s.size();     // 5(推荐,与容器统一)

4.6 常用成员函数

函数 功能 示例
size() / length() 返回长度 s.size()
empty() 判断是否为空 if (s.empty())
clear() 清空字符串 s.clear();
append(str) 追加字符串 s.append(" World");
push_back(ch) 追加字符 s.push_back('!');
insert(pos, str) 在位置pos插入 s.insert(5, " C++");
erase(pos, len) 删除从pos开始的len个字符 s.erase(5, 3);
replace(pos, len, str) 替换子串 s.replace(0, 5, "Hi");
substr(pos, len) 提取子串 std::string sub = s.substr(0, 5);
find(str) 查找子串第一次出现的位置 size_t pos = s.find("lo");
rfind(str) 从右侧查找 size_t pos = s.rfind("l");
find_first_of(chars) 查找任一字符第一次出现 size_t pos = s.find_first_of("aeiou");
compare(str) 比较字符串(返回0表示相等) if (s.compare("Hello") == 0)
c_str() 返回C风格字符串(const char*) const char* cstr = s.c_str();

示例

cpp

复制代码
#include <iostream>
#include <string>

int main() {
    std::string s = "Hello, C++ World!";
    
    // 查找子串
    size_t pos = s.find("C++");
    if (pos != std::string::npos) {
        std::cout << "找到 C++ 在位置 " << pos << std::endl;
    }
    
    // 提取子串
    std::string sub = s.substr(7, 3);   // "C++"
    std::cout << sub << std::endl;
    
    // 替换
    s.replace(7, 3, "Python");
    std::cout << s << std::endl;   // "Hello, Python World!"
    
    // 插入
    s.insert(13, "Programming ");
    std::cout << s << std::endl;   // "Hello, Python Programming World!"
    
    // 删除
    s.erase(13, 12);
    std::cout << s << std::endl;   // "Hello, Python World!"
    
    return 0;
}

4.7 字符串与数值的转换

C++11提供了数值与字符串互转的函数,包含在<string>中。

  • std::to_string(val):将数值转换为字符串

  • std::stoi(str)std::stolstd::stollstd::stofstd::stodstd::stold:将字符串转换为数值

cpp

复制代码
#include <string>
#include <iostream>

int main() {
    int num = 123;
    std::string str = std::to_string(num);   // "123"
    
    std::string s = "456.78";
    double d = std::stod(s);                  // 456.78
    int i = std::stoi(s);                     // 456(截断小数部分)
    
    return 0;
}

4.8 范围for循环遍历字符串

C++11引入的范围for循环可以简洁地遍历字符串中的每个字符。

cpp

复制代码
std::string s = "Hello";
for (char ch : s) {
    std::cout << ch << " ";
}
// 输出:H e l l o

第五章:数组与字符串的综合应用

5.1 示例:学生成绩统计

假设有一个班级,有5名学生,每人有3门课的成绩。我们需要计算每个学生的平均分和每门课的平均分。

cpp

复制代码
#include <iostream>
#include <iomanip>

int main() {
    const int STUDENTS = 5;
    const int SUBJECTS = 3;
    double scores[STUDENTS][SUBJECTS] = {
        {85.5, 90.0, 78.5},
        {88.0, 76.5, 92.0},
        {91.5, 89.0, 84.5},
        {79.0, 85.5, 88.0},
        {94.0, 87.5, 90.5}
    };
    
    // 计算每个学生的平均分
    std::cout << "学生平均分:" << std::endl;
    for (int i = 0; i < STUDENTS; i++) {
        double sum = 0;
        for (int j = 0; j < SUBJECTS; j++) {
            sum += scores[i][j];
        }
        double avg = sum / SUBJECTS;
        std::cout << "学生" << i+1 << ": " << std::fixed << std::setprecision(2) << avg << std::endl;
    }
    
    // 计算每门课的平均分
    std::cout << "\n科目平均分:" << std::endl;
    for (int j = 0; j < SUBJECTS; j++) {
        double sum = 0;
        for (int i = 0; i < STUDENTS; i++) {
            sum += scores[i][j];
        }
        double avg = sum / STUDENTS;
        std::cout << "科目" << j+1 << ": " << std::fixed << std::setprecision(2) << avg << std::endl;
    }
    
    return 0;
}

5.2 示例:字符串处理------统计单词数量

输入一行文本,统计其中单词的数量(假设单词由空格分隔)。

cpp

复制代码
#include <iostream>
#include <string>

int main() {
    std::string line;
    std::cout << "请输入一行文本:";
    std::getline(std::cin, line);
    
    int wordCount = 0;
    bool inWord = false;
    
    for (char ch : line) {
        if (ch == ' ' || ch == '\t' || ch == '\n') {
            inWord = false;
        } else {
            if (!inWord) {
                wordCount++;
                inWord = true;
            }
        }
    }
    
    std::cout << "单词数量:" << wordCount << std::endl;
    return 0;
}

5.3 示例:字符串反转

输入一个字符串,输出它的反转版本。

cpp

复制代码
#include <iostream>
#include <string>

int main() {
    std::string s;
    std::cout << "请输入一个字符串:";
    std::getline(std::cin, s);
    
    int len = s.length();
    for (int i = 0; i < len / 2; i++) {
        char temp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = temp;
    }
    
    std::cout << "反转后:" << s << std::endl;
    return 0;
}

也可以使用标准库的std::reverse(包含<algorithm>):

cpp

复制代码
#include <algorithm>
// ...
std::reverse(s.begin(), s.end());

第六章:常见错误与最佳实践

6.1 数组越界

错误

cpp

复制代码
int arr[5];
for (int i = 0; i <= 5; i++) {  // 当i=5时越界
    arr[i] = i;
}

修正 :使用<而不是<=

6.2 数组名作为指针的陷阱

数组名在大多数情况下会退化为指向首元素的指针,这可能导致sizeof行为变化。例如:

cpp

复制代码
int arr[10];
int *ptr = arr;
std::cout << sizeof(arr) << std::endl;   // 40(10个int)
std::cout << sizeof(ptr) << std::endl;   // 8(指针大小,取决于平台)

在函数参数中,数组会退化为指针,不能直接传递数组大小信息。通常需要额外传递大小参数。

6.3 使用未初始化的数组元素

局部数组如果不初始化,其元素的值是不确定的。务必在使用前初始化。

6.4 C风格字符串忘记空字符

cpp

复制代码
char str[3] = {'a','b','c'};  // 没有'\0',不是合法字符串
std::cout << str;              // 可能输出abc后继续输出垃圾,直到遇到'\0'

6.5 std::stringfind返回值判断

find返回std::string::npos表示未找到,判断时用!=

cpp

复制代码
if (s.find("abc") != std::string::npos) {
    // 找到
}

6.6 避免C风格字符串,优先使用std::string

除非必须与C API交互,否则尽量使用std::string,它更安全、更便捷。

第七章:实践练习------动手写代码!

练习一:数组元素统计

生成一个包含20个随机整数(范围1-100)的数组,然后计算并输出:

  • 所有元素的平均值

  • 最大值及其位置(下标)

  • 最小值及其位置

  • 有多少个元素大于平均值

练习二:数组排序

编写程序,输入10个整数,使用冒泡排序或选择排序将它们按升序排列,并输出排序后的结果。

练习三:二维数组------矩阵乘法

实现两个矩阵的乘法。给定矩阵A(m×n)和B(n×p),计算C = A × B。要求用户输入矩阵的行列数及元素值,输出乘积矩阵。

练习四:字符串判断------回文

输入一个字符串,判断它是否为回文(正读反读都一样),忽略空格和标点符号,不区分大小写。例如:"A man a plan a canal Panama" 是回文。

练习五:字符串统计------字符频率

输入一个字符串,统计每个字母(忽略大小写)出现的次数,并输出出现次数最多的字母及其次数。

练习六:字符串加密------凯撒密码

实现一个简单的凯撒密码加密/解密程序。输入一个字符串和一个位移值(整数),对每个字母进行位移(只处理字母,保持大小写),非字母保持不变。例如,输入"Hello, World!",位移3,输出"Khoor, Zruog!"。

练习七:学生成绩管理系统(综合)

设计一个简单的学生成绩管理系统:

  • 最多存储50名学生,每名学生有学号(整数)、姓名(字符串)、三门课的成绩(整数)

  • 提供菜单:

    1. 添加学生信息

    2. 显示所有学生信息及总分、平均分

    3. 按总分排序显示

    4. 按学号查找学生

    5. 退出

  • 使用数组和字符串实现

练习八:螺旋矩阵

输入一个正整数n(1<=n<=10),生成一个n×n的螺旋矩阵。例如n=4时:

text

复制代码
 1  2  3  4
12 13 14  5
11 16 15  6
10  9  8  7

输出格式整齐。

练习九:字符串解析------计算器

输入一个简单的算术表达式,如"3 + 5 * 2",使用字符串解析提取数字和运算符,计算并输出结果。支持+、-、*、/,考虑运算符优先级。

练习十:单词统计

输入一段英文文本(多行,以空行结束),统计每个单词出现的次数,并按单词字母顺序输出结果(忽略大小写,忽略标点)。可以使用std::map(后续章节),或者用数组模拟。

第八章:常见问题与解答

Q1: 数组大小为什么必须用常量?

A: 在C++标准中,数组大小必须是编译期常量。这是因为数组在栈上分配,编译器需要在编译时知道分配多少内存。如果需要运行时确定大小,应使用动态内存分配(new/delete)或std::vector

Q2: 如何获取数组的长度?

A: 如果数组是静态定义的(不是指针),可以使用sizeof(arr) / sizeof(arr[0])。但更安全的做法是使用std::size(arr)(C++17)或定义常量保存长度。对于函数参数中的数组(实际是指针),这种方法无效。

Q3: std::stringchar[]有什么区别?

A: std::string是一个类,封装了字符数组,自动管理内存,提供丰富的成员函数,使用安全。char[]是原始字符数组,需要手动处理空字符、长度和边界,容易出错。现代C++推荐使用std::string

Q4: std::stringc_str()有什么用?

A: 当需要将std::string传递给接受const char*的C函数时,使用c_str()获取底层字符数组的指针。注意返回的指针在std::string被修改或销毁后会失效。

Q5: 二维数组在内存中如何存储?

A: 二维数组按行优先存储:先存储第一行的所有元素,然后是第二行,依此类推。所有元素在内存中是连续的一段空间。

Q6: 如何将字符串转换为大写或小写?

A: 可以使用std::transform配合touppertolower(包含<algorithm><cctype>):

cpp

复制代码
#include <algorithm>
#include <cctype>
#include <string>

std::string s = "Hello";
std::transform(s.begin(), s.end(), s.begin(), ::toupper);

Q7: 为什么std::stringfind返回size_t而不是int

A: size_t是无符号类型,通常与指针大小相同,能表示所有可能的索引。当未找到时,返回std::string::npos,其值为static_cast<size_t>(-1)。因此,判断是否找到应该用if (pos != std::string::npos)而不是if (pos >= 0)(因为size_t永远≥0)。

第九章:下一站预告

恭喜你完成了第六篇!现在你已经掌握了批量数据存储(数组)和文本处理(字符串)的核心知识。你能处理成百上千个数据,能解析和操作文本信息,你的程序能力又上了一个台阶。

在下一篇中,我们将进入C++的核心特性之一:函数。函数是模块化编程的基础,它让你能够将代码组织成可复用的单元,使程序结构更清晰、更易于维护。我们将学习:

  • 函数的定义与调用

  • 参数传递(值传递、引用传递)

  • 返回值

  • 函数重载

  • 默认参数

  • 内联函数

  • 函数的作用域与生命周期

  • 递归

掌握函数后,你将能够编写出结构清晰、高度复用的代码,这是从"写程序"到"设计程序"的飞跃。

结语:批量处理打开新世界

数组让我们能够处理大量数据,字符串让我们能够与用户进行有意义的文本交互。结合之前学习的循环和选择,你可以编写出很多实用程序了:成绩统计、文本分析、简单游戏......编程的世界正在你面前展开。

请务必完成本章的练习,尤其是综合性的学生成绩管理系统和螺旋矩阵等题目。它们能帮助你巩固数组和字符串的知识,并锻炼综合运用能力。

记住,编程不仅是学会语法,更重要的是学会如何用这些工具解决问题。每一次练习,都是一次思维训练。

现在,去写代码吧!让数组和字符串为你服务。我们下一篇见!

相关推荐
小陈工2 小时前
2026年3月23日技术资讯洞察:AI Agent失控,Claude Code引领AI编程新趋势
开发语言·数据库·人工智能·后端·python·性能优化·ai编程
liulilittle2 小时前
LINUX RING BUFFER TUN/TAP 2
linux·运维·服务器·开发语言·网络·c++
阿里嘎多哈基米2 小时前
速通Hot100-Day10——二叉树
算法·leetcode·二叉树·递归·平衡二叉树
chushiyunen2 小时前
BM25稀疏检索算法笔记
笔记·算法·c#
芸忻2 小时前
day 23 第七章 回溯算法part02代码随想录算法训练营71期
算法
妙蛙种子3112 小时前
【Java八股 |JUC并发编程类】线程
java·开发语言·后端·多线程·八股
qq_334903152 小时前
C++中的装饰器模式高级应用
开发语言·c++·算法
jyyyx的算法博客2 小时前
LC406. 基于身高重建队列【贪心】
算法
忙什么果2 小时前
class_weight=‘balanced‘缓解类别不平衡问题
算法·机器学习·支持向量机