news 2026/7/2 2:20:06

C++ 结构体与结构体数组详解:定义、排序与实战应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ 结构体与结构体数组详解:定义、排序与实战应用

导读:在实际开发中,我们经常需要把多个不同类型的数据绑定在一起表示一个实体——比如一个学生的学号(int)、姓名(string)、成绩(double)。C++ 的struct就是做这件事的。本文从结构体的定义讲起,逐步扩展到结构体数组、结构体排序,最后通过三道经典题目演示结构体在实战中的应用。


一、结构体是什么?

C++ 内置的类型(intdoublestring)一次只能存一个值。但现实中的数据往往是"一组一组"出现的:一个学生有学号、姓名、年龄、成绩等多个属性,一个坐标有 x 和 y 两个值。

**结构体(struct)**就是把多个不同类型的变量打包成一个自定义类型:

// 定义一个"学生"结构体structstudent{intnum;// 学号string name;// 姓名intage;// 年龄doublescore;// 成绩};

定义完成后,student就和intstring一样,是一个可用的类型了。

C vs C++ 小知识:C 语言中习惯用typedef struct student {} student;来简化命名。C++ 中直接写struct student {}就行,typedef可以省略,使用时也不需要加struct关键字。


二、创建和使用结构体变量

2.1 用结构体类型创建变量

定义好结构体后,可以像内置类型一样创建变量:

student st;// 创建一个学生变量st.num=1001;// 用 "." 访问成员st.name="张三";st.age=20;st.score=95.5;

st.num就像"张三的学号",.运算符用来访问结构体内部的某个字段。

2.2 创建时直接初始化

也可以在创建的同时赋值:

student st={1002,"李四",21,88.0};

字段按照定义顺序依次赋值,不想赋值的可以留空(默认初始化为 0 或空字符串)。

2.3 用typedef给结构体起别名

如果嫌struct student写起来太长,可以用typedef起个短名字:

typedefstructstudent{intnum;string name;intage;doublescore;}stu;// stu 就是 struct student 的别名stu st1;// 和 student st1; 等价stu st2;

三、结构体数组:把多个"对象"放在一起

一个student变量只能存一个学生的信息。如果要存全班 50 个学生呢?这就需要结构体数组

3.1 普通数组形式

stu arr[50];// 创建一个能存 50 个学生的数组// 访问第 i 个学生的学号arr[0].num=1001;arr[1].name="王五";

和普通数组一样用[]取下标,然后.取字段。

3.2 vector 形式(推荐)

实际开发中更推荐用vector,因为大小可以动态调整:

vector<stu>vec;// 创建一个临时变量,填充数据后 push 进去stu s;s.num=1001;s.name="张三";s.score=95.5;vec.push_back(s);// 也可以直接在 push_back 时用花括号构造(C++11)vec.push_back({1002,"李四",21,88.0});

技巧:如果数据量已知,可以直接创建指定大小的 vector:

vector<stu> vec(50); // 预分配 50 个位置,每个字段默认初始化 vec[1].num = 1001;

3.3 遍历结构体 vector

// 增强 for 循环遍历for(auto&s:vec){cout<<s.num<<" "<<s.name<<" "<<s.score<<endl;}

用引用&避免拷贝,提高效率。


四、结构体排序:sort + lambda 表达式

这是结构体最实用的考点。实际题目中,我们经常需要对学生按成绩排序、对坐标按 x 排序等等。关键在于:怎么告诉sort按结构体的哪个字段来排?

4.1 基本用法

用 lambda 表达式指定排序规则:

vector<stu>vec={{1001,"张三",20,95.5},{1002,"李四",21,88.0},{1003,"王五",19,92.0}};// 按成绩从高到低排序sort(vec.begin(),vec.end(),[](conststu&a,conststu&b){returna.score>b.score;// a 的成绩 > b 的成绩时,a 排在前面});

lambda 表达式的规则很简单:参数是两个待比较的元素abreturn true表示a应该排在b前面。

4.2 多字段排序

实际题目经常要求"成绩相同则按学号排"这种多级排序:

// 先按成绩降序,成绩相同则按学号升序sort(vec.begin(),vec.end(),[](conststu&a,conststu&b){if(a.score!=b.score)returna.score>b.score;returna.num<b.num;});

逻辑是:先比第一个字段,如果相等再比第二个字段,以此类推。用if逐级判断即可。


五、实战题目

5.1 谁考了第 k 名

题目:输入 n 个学生的学号和成绩,按成绩从高到低排序后输出第 k 名的学号和成绩。

思路:用结构体存学号和成绩,排序后直接取第 k-1 个元素。

#include<bits/stdc++.h>usingnamespacestd;structstu{string num;// 学号doublescore;// 成绩};vector<stu>vec;intmain(){intn,k;cin>>n>>k;for(inti=0;i<n;i++){stu s;cin>>s.num>>s.score;vec.push_back(s);}// 按成绩降序排序sort(vec.begin(),vec.end(),[](conststu&a,conststu&b){returna.score>b.score;});// 第 k 名就是下标 k-1(下标从 0 开始)cout<<vec[k-1].num<<" "<<vec[k-1].score;return0;}

关键点:结构体只定义需要的字段,不要贪多。这道题只需要学号和成绩,就不用加 name 和 age。

5.2 奖学金

题目:输入 n 个学生的语文、数学、英语成绩,计算总分后按以下规则排序取前 5 名:

  1. 总分高的在前
  2. 总分相同,语文成绩高的在前
  3. 总分和语文都相同,学号小的在前

这是一道经典的三级排序题,排序规则稍微复杂但逻辑清晰。

思路:结构体里存学号、各科成绩和总分,用 lambda 实现三级排序。

#include<bits/stdc++.h>usingnamespacestd;structsc{intnum;// 学号intchin;// 语文intmath;// 数学inteng;// 英语intscore;// 总分};vector<sc>vec;intmain(){intn;cin>>n;for(inti=1;i<=n;i++){sc s;s.num=i;cin>>s.chin>>s.math>>s.eng;s.score=s.chin+s.math+s.eng;// 计算总分vec.push_back(s);}// 三级排序:总分 -> 语文 -> 学号sort(vec.begin(),vec.end(),[](constsc&a,constsc&b){if(a.score!=b.score)returna.score>b.score;if(a.chin!=b.chin)returna.chin>b.chin;returna.num<b.num;});// 输出前 5 名for(inti=0;i<5;i++){cout<<vec[i].num<<" "<<vec[i].score<<endl;}return0;}

关键点:多级排序时,每一级判断完!=后再进入下一级,这样逻辑最清晰,不会出错。

5.3 合并区间(LeetCode 56)

题目:给定若干个区间[start, end],将所有有重叠的区间合并。

虽然这道题用的是vector<vector<int>>而非自定义结构体,但它的核心思路和结构体排序完全一致——先按某个字段排序,再遍历处理

思路:先按区间左端点排序,然后遍历判断相邻区间是否重叠。重叠则合并(取更大的右端点),不重叠则直接加入结果。

classSolution{public:vector<vector<int>>merge(vector<vector<int>>&intervals){if(intervals.empty())returnintervals;// 按区间左端点升序排序sort(intervals.begin(),intervals.end(),[](constvector<int>&a,constvector<int>&b){returna[0]<b[0];});vector<vector<int>>result;result.push_back(intervals[0]);// 先把第一个区间放进去for(inti=1;i<intervals.size();i++){// 当前区间的左端点 <= 结果中最后一个区间的右端点 → 重叠if(intervals[i][0]<=result.back()[1]){// 合并:取更大的右端点result.back()[1]=max(result.back()[1],intervals[i][1]);}else{// 不重叠:直接加入结果result.push_back(intervals[i]);}}returnresult;}};

关键点:result.back()取的是结果中最后一个区间,用它来判断是否和当前区间重叠。这种"先排序再贪心合并"的思路在很多区间类题目中都适用。


六、总结

知识点关键内容
结构体定义struct 名字 { 字段... };,不同类型数据打包
成员访问.运算符:st.name
结构体数组普通数组stu arr[N]vector<stu>
结构体排序sort+ lambda 表达式指定比较字段
多级排序if (字段1 != 字段1) return 比较; if (字段2 != 字段2) return 比较;
typedeftypedef struct xxx {} 别名;,简化类型名

结构体是 C++ 中连接"数据"和"逻辑"的桥梁。后续学习链表、二叉树等数据结构时,节点本质上就是结构体。把结构体用熟练,后面的内容会轻松很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 2:19:35

AI 辅助:独立创作:工具应放大作者,而不是替代作者

AI 辅助&#xff1a;独立创作&#xff1a;工具应放大作者&#xff0c;而不是替代作者 一、创作工具的边界是保留人的选择权 AI 辅助独立创作很容易走向两个极端&#xff1a;一种把 AI 当成万能写手&#xff0c;期待它一键生成完整作品&#xff1b;另一种完全排斥 AI&#xff0c…

作者头像 李华
网站建设 2026/7/2 2:19:25

InfiniBand与以太网页故障处理机制对比分析

1. InfiniBand与以太网页故障处理机制概述在现代高性能计算和分布式系统中&#xff0c;虚拟内存管理和网络通信是两个至关重要的基础组件。当这两个领域交汇时&#xff0c;页故障&#xff08;Page Fault&#xff09;处理机制的设计直接影响到系统的性能和可靠性。页故障是指当进…

作者头像 李华
网站建设 2026/7/2 2:18:48

AI 边缘推理部署:先算清内存,再谈模型效果

AI 边缘推理部署&#xff1a;先算清内存&#xff0c;再谈模型效果 一、边缘 AI 最先卡住的不是算法 在服务器上跑模型&#xff0c;很多问题可以靠显存和算力兜住&#xff1b;到了边缘设备&#xff0c;第一堵墙通常是内存。Flash 放不下权重&#xff0c;SRAM 放不下中间张量&…

作者头像 李华
网站建设 2026/7/2 2:17:02

42.llama_index-说明

内容参考于&#xff1a;图灵AI大模型全栈 langchain去搞Agent了对RAG兼容性太差了&#xff0c;可以说没有RAG的功能了&#xff0c;这里停止更新langchain&#xff0c;接下来开始写新的框架llama_index&#xff0c;它好使 LLama_index框架 api文档地址:https://developers.lla…

作者头像 李华
网站建设 2026/7/2 2:16:26

基于范围的for循环

在上面的语法格式中Type declaration表示遍历声明&#xff0c;在遍历过程中&#xff0c;当前被遍历导的元素会被存储到声明的变量declaration中。expression是要遍历的对象&#xff0c;它可以是表达式、容器、数组、初始化列表等。 如下代码&#xff1a; #include <iostre…

作者头像 李华
网站建设 2026/7/2 2:13:53

c++复习自存

static 静态变量用途 一、函数内部 static 局部变量 核心特点 存储在全局静态存储区&#xff0c;不是栈&#xff1b;程序启动分配内存、程序结束才销毁只初始化1次&#xff0c;首次进入函数执行初始化&#xff0c;后续调用跳过初始化作用域仍仅限当前函数&#xff0c;外部无…

作者头像 李华