计算方法实验5:对鸢尾花数据集进行主成分分析(PCA)并可视化

news2024/9/23 23:31:56

任务

iris数据集包含150条数据,从iris.txt读取,每条数据有4个属性值和一个标签(标签取值为0,1,2)。要求对这150个4维数据进行PCA,可视化展示这些数据在前两个主方向上的分布,其中不同标签的数据需用不同的颜色或形状加以区分。

算法

m个n维数据向量去中心化后(各向量的每个维度减去这个维度在所有向量上均值),按列排列构成矩阵 X n × m \mathbf{X}_{n\times m} Xn×m,计算协方差矩阵 V a r n × n = 1 m X X T \mathbf{Var}_{n\times n}= \frac{1}{m}\mathbf{XXT} Varn×n=m1XXT的特征值,选取最大两个特征值对应的特征向量构成矩阵 P 2 × n \mathbf{P}_{2\times n} P2×n,则 Y 2 × m = P X \mathbf{Y}_{2\times m}=\mathbf{PX} Y2×m=PX即PCA后的结果,也就是把四维数据压缩为二维,每个数据对应二维平面上的一个点。
对PCA的详解,可以参考这篇文章;关于PCA与奇异值分解的联系,可以参考这篇文章;关于如何用C++求矩阵特征值(Jacobi方法)和特征向量及对矩阵进行奇异值分解,可以参考这篇文章。

代码

C++实现PCA

#include<bits/stdc++.h>
using namespace std;

// 读取鸢尾花数据集到一个二维数组中
vector<vector<long double>> readIrisData(const string& filename);

// 读取第五列的值到一个向量中
vector<long double> readfifthValue(const string& filename);

// 从矩阵 A 非对角元中选择最大的元素,并返回其位置
pair<int, int> chooseMax(vector<vector<long double>> A);

// 计算矩阵 A 的转置
vector<vector<long double>> calAT(vector<vector<long double>> A);

// 计算矩阵 A 和其转置的乘积
vector<vector<long double>> calAAT(vector<vector<long double>> A);

// 计算矩阵Q^T * A * Q的每个元素,使用给定的参数 p, q, t, c, d
long double calculateElement(const vector<vector<long double>> A, int i, int j, long double p, long double q, long double t, long double c, long double d);

// 计算矩阵 Q^T * A * Q
vector<vector<long double>> calQTAQ(vector<vector<long double>> A);

// 判断Jacobi迭代方法是否满足结束条件
int judgeEnd(vector<vector<long double>> A);

// 计算矩阵 A 的特征值
vector<long double> calEigenValue(vector<vector<long double>> A);

// 对矩阵 A 进行列主元化成上三角
vector<vector<long double>> Column_Elimination(vector<vector<long double>> A);

// 求解系数矩阵为上三角矩阵A的线性方程组
vector<long double> SolveUpperTriangle(vector<vector<long double>> A, vector<long double> b);

// 解系数矩阵为上三角矩阵 A 的线性方程组,且A全为0的行数为 cnt
vector<vector<long double>> solve(vector<vector<long double>> A, int cnt);

// 计算矩阵 A 的特征向量,使用给定的特征值
vector<vector<long double>> calEigenVector(vector<vector<long double>> A, vector<long double> eigenValue);

// 计算 Sigma 矩阵,使用给定的特征值 x 和矩阵的行数 n1 和列数 n2
vector<vector<long double>> calSigma(vector<long double> x,int n1, int n2);

// 计算向量 x 的欧几里得范数
long double EuclideanNorm(vector<long double> x);

// 对矩阵 A 进行归一化
vector<vector<long double>> Normalization(vector<vector<long double>> A);

// 计算矩阵 A 和 B 的乘积
vector<vector<long double>> multiplyMatrices(const vector<vector<long double>> A, const vector<vector<long double>> B);

int main()
{
    vector<vector<long double>> X = calAT(readIrisData("iris.txt"));
    int n1 = X.size();
    int n2 = X[0].size();
    long double sum = 0;
    for(int i = 0; i < n1; i++)
    {
        long double sum = 0;
        for(int j = 0; j < n2; j++)
            sum += X[i][j];
        long double avg = sum / n2;
        for(int j = 0; j < n2; j++)
            X[i][j] -= avg;
    }
    cout << "X: " << endl;
    for(int i = 0; i < n1; i++)
    {
        for(int j = 0; j < n2; j++)
            cout << X[i][j] << " ";
        cout << endl;
    }
    vector<vector<long double>> XT = calAT(X);
    vector<vector<long double>> XXT = multiplyMatrices(X, XT);
    vector<vector<long double>> Var(n1, vector<long double>(n1));
    for(int i = 0; i < n1; i++)
        for(int j = 0; j < n1; j++)
            Var[i][j] = XXT[i][j] / n2;
    vector<long double> x =calEigenValue(Var);
    sort(x.begin(), x.end());
    reverse(x.begin(), x.end());
    cout<<"特征值:"<<endl;
    for(int i = 0; i < n1; i++)
        cout << x[i] << " ";
    vector<long double> x1;
    x1.reserve(x.size());
    unique_copy(x.begin(), x.end(), back_inserter(x1));
    vector<vector<long double>> EigenVector = Normalization(calEigenVector(Var, x1));
    vector<vector<long double>> P(EigenVector.begin(), next(EigenVector.begin(), 2));
    cout << "P: " << endl;
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < n1; j++)
            cout << P[i][j] << " ";
        cout << endl;
    }
    vector<vector<long double>> Y = multiplyMatrices(P, X);
    cout << "Y: " << endl;
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < n2; j++)
            cout << Y[i][j] << " ";
        cout << endl;
    }
    return 0;
}

// 读取鸢尾花数据集到一个二维数组中
vector<vector<long double>> readIrisData(const string& filename) {
    ifstream file(filename);
    vector<vector<long double>> X;
    string line;

    while (getline(file, line)) {
        stringstream ss(line);
        vector<long double> row;
        string value;
        int counter = 0;
        while (getline(ss, value, ',') && counter < 4) {
            row.push_back(stod(value));
            counter++;
        }
        X.push_back(row);
    }
    return X;
}

// 读取第五列的值到一个向量中
vector<long double> readfifthValue(const string& filename) {
    ifstream file(filename);
    vector<long double> fifthValues;
    string line;

    while (getline(file, line)) {
        stringstream ss(line);
        string value;
        int counter = 0;
        while (getline(ss, value, ',') && counter < 4) {
            counter++;
        }
        if (counter == 4) { 
            long double fifthValue = stold(value);
            fifthValues.push_back(fifthValue);
        }
    }
    return fifthValues;
}

// 找到矩阵 A 中非对角元中绝对值最大的元素,并返回其位置
pair<int, int> chooseMax(vector<vector<long double>> A)
{
    long double max = 0;
    pair<int, int> maxPos;
    int n = A.size();
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            if(i != j && fabsl(A[i][j]) > max)
            {
                max = fabsl(A[i][j]);
                maxPos = make_pair(i, j);
            }
    return maxPos;
}

// 计算矩阵 A 的转置
vector<vector<long double>> calAT(vector<vector<long double>> A)
{
    int n1 = A.size();
    int n2 = A[0].size();
    vector<vector<long double>> AT(n2, vector<long double>(n1));
    for(int i = 0; i < n1; i++)
        for(int j = 0; j < n2; j++)
            AT[j][i] = A[i][j];
    return AT;
}

// 计算两个矩阵的乘积
vector<vector<long double>> multiplyMatrices(const vector<vector<long double>> A, const vector<vector<long double>> B) {
    int n1 = A.size();
    int n2 = B[0].size();
    int n3 = A[0].size();
    vector<vector<long double>> result(n1, vector<long double>(n2, 0.0));

    for(int i = 0; i < n1; i++) {
        for(int j = 0; j < n2; j++) {
            for(int k = 0; k < n3; k++) {
                result[i][j] += A[i][k] * B[k][j];
            }
        }
    }
    return result;
}

// 计算矩阵Q^T * A * Q的每个元素,使用给定的参数 p, q, t, c, d
long double calculateElement(const vector<vector<long double>> A, int i, int j, long double p, long double q, long double t, long double c, long double d) {
    if (i == p && j == p)
        return A[p][p] - t * A[p][q];
    else if (i == q && j == q)
        return A[q][q] + t * A[p][q];
    else if ((i == p && j == q) || (i == q && j == p))
        return 0;
    else if (i != q && i != p && (j == p || j == q))
        return (j == p ? c : d) * A[p][i] - (j == p ? d : (-c)) * A[q][i];
    else if ((i == p || i == q) && j != q && j != p)
        return (i == p ? c : d) * A[p][j] - (i == p ? d : (-c)) * A[q][j];
    else
        return A[i][j];
}

// 计算矩阵 Q^T * A * Q
vector<vector<long double>> calQTAQ(vector<vector<long double>> A)
{
    int n = A.size();
    pair<int, int> maxPos = chooseMax(A);
    int row = maxPos.first;
    int col = maxPos.second;
    
    long double s = (A[col][col] - A[row][row]) / (2 * A[row][col]);
    long double t = 0;
    if(s == 0)
        t = 1;
    else if(abs(-s + sqrt(1 + s * s)) <= abs(-s - sqrt(1 + s * s)))
        t = -s + sqrt(1 + s * s);
    else
        t = -s - sqrt(1 + s * s);

    long double c = 1 / sqrt(1 + t * t);
    long double d = t * c;

    vector<vector<long double>> QTAQ(n, vector<long double>(n));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            QTAQ[i][j] = calculateElement(A, i, j, row, col, t, c, d);
    return QTAQ;
}

// 判断Jacobi迭代方法是否满足结束条件
int judgeEnd(vector<vector<long double>> A)
{
    int i, j;
    int n = A.size();
    for(i = 0; i < n; i++)
        for(j = 0; j < n; j++)
            if(i != j && fabsl(A[i][j]) >= 1e-6)
                return 0;
    if(i == n && j == n) 
        return 1;
}

// 计算矩阵 A 的特征值
vector<long double> calEigenValue(vector<vector<long double>> A)
{
    int n = A.size();
    vector<long double> eigenValue(n);
    vector<vector<long double>> QTAQ= calQTAQ(A);
    int i, j;
    while(!judgeEnd(QTAQ))
        QTAQ = calQTAQ(QTAQ);
    for(i = 0; i < n; i++)
        eigenValue[i] =QTAQ[i][i];
    return eigenValue;
}

// 对矩阵 A 进行列主元化成上三角
vector<vector<long double>> Column_Elimination(vector<vector<long double>> A)
{
    int n = A.size();
    vector<vector<long double>> Temp(n, vector<long double>(n));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            Temp[i][j] = A[i][j];
    for(int col = 0; col < n; col++)
    {
        long double maxnum = abs(Temp[col][col]);
        int maxrow = col;
        for(int row = col + 1; row < n; row++)
        {
            if(abs(Temp[row][col]) > maxnum)
            {
                maxnum = abs(Temp[row][col]);
                maxrow = row;
            }
        }
        swap(Temp[col], Temp[maxrow]);
        for(int row = col + 1; row < n; row++)
        {
            long double res = Temp[row][col] / Temp[col][col];
            for(int loc = col; loc < n; loc++)
                Temp[row][loc] -= Temp[col][loc] * res; 
        }
    }
    return Temp;
}

// 求解系数矩阵为上三角矩阵A的线性方程组
vector<long double> SolveUpperTriangle(vector<vector<long double>> A, vector<long double> b)
{
    int n = A.size();
    vector<long double> x(n);
    vector<vector<long double>> Temp(n, vector<long double>(n+1));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            Temp[i][j] = A[i][j];
    for(int i = 0; i < n; i++)
        Temp[i][n] = b[i];
    for(int row = n-1; row >= 0; row--)
    {
        for(int col = row + 1; col < n; col++)
        {
            Temp[row][n] -= Temp[col][n] * Temp[row][col] / Temp[col][col];
            Temp[row][col] = 0;
        }
        Temp[row][n] /= Temp[row][row];
        Temp[row][row] = 1;
    }
    for(int i = 0; i < n; i++)
        x[i] = Temp[i][n];
    return x;
}

// 解系数矩阵为上三角矩阵 A 的线性方程组,且A全为0的行数为 cnt
vector<vector<long double>> solve(vector<vector<long double>> A, int cnt)
{
    int n = A.size();
    vector<vector<long double>> x(cnt, vector<long double>(n));
    vector<vector<long double>> Temp(n-cnt, vector<long double>(n-cnt));
    vector<long double> Tempb(n-cnt);
    for(int i = 0; i < cnt; i++)
    {
        for(int j = n - 1; j >= n - cnt; j--)
        {
            if(j >= n - i)
                x[i][j] = 0;
            else
                x[i][j] = 1;
        }
    }
    for(int i = 0; i < n - cnt; i++)
        for(int j = 0; j < n - cnt; j++)
            Temp[i][j] = A[i][j];
    for(int i = 0; i < cnt; i++)
    {
        for(int j = n - cnt - 1; j >=  0; j--)
        {
            Tempb[j] = 0;
            for(int k = 0; k < cnt; k++)
                Tempb[j] -= A[j][n- cnt + k] * x[i][n- cnt + k];
        }
        vector<long double> res = SolveUpperTriangle(Temp, Tempb);
        for(int j = 0; j < n - cnt; j++)
            x[i][j] = res[j];
    }
    return x;
}

// 使用给定的特征值计算矩阵 A 的特征向量
vector<vector<long double>> calEigenVector(vector<vector<long double>> A, vector<long double> eigenValue)
{
    int n = A.size();
    int num = 0;
    vector<vector<long double>> x(n, vector<long double>(n));
    vector<vector<long double>> tempMartix(n, vector<long double>(n));
    vector<vector<long double>> eigenVector(n, vector<long double>(n));
    for(int k = 0; k < n; k++)
    {
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                i == j ? tempMartix[i][j] = A[i][j] - eigenValue[k] : tempMartix[i][j] = A[i][j];

        vector<vector<long double>> B = Column_Elimination(tempMartix);
        int cnt = 0;//记录消元后全为0的行数
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(fabsl(B[i][j]) > 1e-7)
                    break;
                else if(j == n - 1)
                    cnt++;
            }
        }
        vector<vector<long double>> result = solve(B, cnt);
        for(int i = 0; i < cnt; i++)
            copy(result[i].begin(), result[i].end(), x[num + i].begin());
        num += cnt;
    }
    return x;
}

// 使用给定的特征值 x 和矩阵的行数 n1 和列数 n2,计算 Sigma 矩阵
vector<vector<long double>> calSigma(vector<long double> x, int n1, int n2)
{
    vector<vector<long double>> Sigma(n1, vector<long double>(n2));
    for(int i = 0; i < min(n1, n2); i++)
        Sigma[i][i] = sqrt(x[i]);
    return Sigma;
}

// 计算向量 x 的欧几里得范数
long double EuclideanNorm(vector<long double> x)
{
    long double norm = 0;
    for(int i = 0; i < x.size(); i++)
        norm += x[i] * x[i];
    return sqrt(norm);
}

// 对矩阵 A 进行归一化
vector<vector<long double>> Normalization(vector<vector<long double>> A)
{
    int rows = A.size();
    for(int i = 0; i < rows; i++)
    {
        long double norm = EuclideanNorm(A[i]);
        int cols = A[i].size();
        for(int j = 0; j < cols; j++)
            A[i][j] /= norm;
    }
    return A;
}

python实现PCA并将结果可视化

import numpy as np
from scipy.linalg import eigh
import matplotlib.pyplot as plt

def readIrisData(filename):
    data = np.genfromtxt(filename, delimiter=',', dtype='float', encoding=None)
    return data[:, :4].T, data[:, 4]

X, labels = readIrisData("iris.txt")

Var = np.cov(X)
x, EigenVector = eigh(Var)
x = sorted(x, reverse=True)

P = EigenVector[:, -2:].T
Y = np.dot(P, X)

plt.figure()
label_set = set(labels)
colors = ['r', 'g', 'b']
shapes = ['o', 's', '^']

for i, label in enumerate(label_set):#enumerate函数返回每个标签及其索引
    x = [Y[0, j] for j in range(Y.shape[1]) if labels[j] == label]
    y = [Y[1, j] for j in range(Y.shape[1]) if labels[j] == label]
    plt.scatter(x, y, color=colors[i], marker=shapes[i], label=label)

plt.legend()#添加图例
plt.show()

可视化结果

在这里插入图片描述

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

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

相关文章

鸿蒙原生应用元服务-访问控制(权限)开发Stage模型向用户申请授权

一、向用户申请授权 当应用需要访问用户的隐私信息或使用系统能力时&#xff0c;例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等&#xff0c;应该向用户请求授权。这需要使用 user_grant 类型权限。在此之前&#xff0c;应用需要进行权限校验&#xff0c;以判断当前…

Golang教程一(环境搭建,变量,数据类型,数组切片map)

目录 一、环境搭建 1.windows安装 2.linux安装 3.开发工具 二、变量定义与输入输出 1.变量定义 2.全局变量与局部变量 3.定义多个变量 4.常量定义 5.命名规范 6.输出 格式化输出 7.输入 三、基本数据类型 1.整数型 2.浮点型 3.字符型 4.字符串类型 转义字…

贝叶斯公式中的先验概率、后验概率、似然概率

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

Neo4j 图形数据库中有哪些构建块?

Neo4j 图形数据库具有以下构建块 - 节点属性关系标签数据浏览器 节点 节点是 Graph 的基本单位。 它包含具有键值对的属性&#xff0c;如下图所示。 NEmployee 节点 在这里&#xff0c;节点 Name "Employee" &#xff0c;它包含一组属性作为键值对。 属性 属性是…

华为HarmonyOS 4.2公测升级计划扩展至15款新机型

华为近日宣布&#xff0c;HarmonyOS 4.2操作系统的公测升级计划将扩展到包括华为P50系列在内的15款设备。这一更新旨在为用户提供更优化的系统性能和增强的功能。 参与此次公测的机型包括华为P50、华为P50 Pro及其典藏版、华为P50E、华为P50 Pocket及其艺术定制版、华为nova系…

Unity开发HoloLens2应用时,用VisualStudio进行真机在线Debug调试

一、需求 用Unity开发的应用&#xff0c;部署到真机设备出现启动崩溃&#xff0c;此时可以用在线调试&#xff0c;排查错误。 二、开发环境说明 MRholoLens2 Unity 2021.3.18 Win Win10 VS vs2022 三、调试操作步骤 1、HoloLens2与电脑的连接&#xff0c;Wifi连接&…

不是所有商业模式都叫传销!七星创客模式!

“商业模式是否等同于拉人头、传销&#xff1f;”近期&#xff0c;这一疑问在许多人心中萦绕。似乎每当提及商业模式&#xff0c;总有些人会将其与拉人头、传销等概念联系起来&#xff0c;仿佛所有的商业模式都带有某种负面色彩。 然而&#xff0c;商业模式的内涵远非如此单一。…

MCU的最佳存储方案CS创世 SD NAND

MCU的最佳存储方案CS创世 SD NAND 写在最前面MCU是什么CS创世 SD NAND 6大优势 写在最前面 转载自 雷龙官网 MCU是什么 大家都知道MCU是一种"麻雀"虽小&#xff0c;却"五脏俱全"的主控。它的应用领域非常广泛&#xff0c;小到手机手表&#xff0c;大到航空…

【服务器部署篇】Linux下Jenkins安装和配置

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0c;产…

使用PL\SQL将Excel表格导入到oracle数据库中

因为要测试生产问题&#xff0c;需要把生产上oracle导出数据导入到测试环境oracle数据库中&#xff0c;尝试了N种方法&#xff0c;发现使用PL\SQL 的ODBC 方法比较好用 1、开始 首先使用plsqldev里面的&#xff0c;工具--》下面的odbc导入器 2、配置 点击之后&#xff0c;会…

获取jd.item_get-获得京东商品详情API接口请求参数请求接入示例免费接入KEY演示

京东商品详情API接口的主要作用是&#xff1a; 获取基本信息&#xff1a;包括商品的名称、品牌、产地和规格参数等&#xff0c;这些信息有助于构建商品的基本档案。价格信息获取&#xff1a;可以了解到商品的原价、促销价以及参与的各种活动信息&#xff0c;这对于制定销售策略…

DePT: Decoupled Prompt Tuning 论文阅读

DePT: Decoupled Prompt Tuning 了论文阅读 Abstract1. Introduction2. Methodology2.1. Preliminaries2.2. A Closer Look at the BNT Problem2.3. Decoupled Prompt Tuning 3. Experiments5. Conclusions 文章信息&#xff1a; 原文链接&#xff1a;https://arxiv.org/abs/…

微软搭建零售新媒体创意工作室大举抢占数字营销广告市场

“微软新零售创意工作室新平台利用生成式人工智能&#xff0c;在几秒钟内轻松定制横幅广告。零售媒体预计到2026年将成为一个价值1000亿美元的行业。” 零售媒体在过去几年中发展迅速。根据eMarketerOpens在新窗口的数据&#xff0c;预计到2024年&#xff0c;仅美国的零售媒体…

COOIS增加增强字段

SAP系统标准的工单信息报表COOIS增加客制化增强字段可以按照以下步骤处理&#xff1b; 1. 在显示抬头信息的输出结构IOHEADER中增加需要显示的增强字段 2. 使用BADI WORKORDER_INFOSYSTEM创建增强实施 3. 在方法TABLES_MODIFY_LAY中处理相应字段的取值逻辑

YoloV8改进策略:Block改进|轻量级的Mamba打造优秀的YoloV8|即插即用,简单易懂|附Block结构图|检测、分割、关键点均适用(独家原创)

摘要 无Mamba不狂欢,今天给大家带来一个基于轻量级Mamba的改进。模块简单易懂,即插即用! 带领大家去征服更高的领域。 论文:《LightM-UNet:Mamba 辅助的轻量级 UNet 用于医学图像分割》 https://arxiv.org/pdf/2403.05246.pdf UNet及其变体在医学图像分割中得到了广泛…

Thread和Runnable

两者都创建线程的方式&#xff0c;不同之处在于前者是类&#xff0c;后者是接口。使用的时候重写他们即可。 预热&#xff1a;操作系统的知识 想象此时有一条马路&#xff0c;走的人多了道路开始变得堵塞&#xff0c;如果拓宽为多车道即可解决该问题。 这便是多线程的例子。…

An Investigation of Geographic Mapping Techniques for Internet Hosts(2001年)第二部分

​下载地址:An investigation of geographic mapping techniques for internet hosts | Proceedings of the 2001 conference on Applications, technologies, architectures, and protocols for computer communications 被引次数:766 Padmanabhan V N, Subramanian L. An i…

Redis限流插件

Redis限流插件: 1:搭建层级结构 同时对 redis.log 授权 chmod 777 redis.log2:确认 redis 版本 3:下载redis配置文件 redis.conf https://redis.io/docs/management/config/ 4:上传/redis/conf作为原始 redis.conf 5:在/redis_6390/conf下编辑redis.conf docker run -it \ --…

软件测试面试题分享(含答案+文档)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 准备找工作的小伙伴们&#xff0c;今天我给大家带来了一些自动化测试面试题&#xff0c;在这个公…

c++的学习之路:4、入门(3)

摘要 本章将介绍一下auto、for和指针空值&#xff0c;文章末附上入门的所有代码。 目录 摘要 一、auto 二、for 三、指针空值 四、代码 五、思维导图 一、auto 这个关键字是c提出的&#xff0c;可以自动识别变量的类型&#xff0c;可以看出下方图片&#xff0c;auto自…