C++知识点总结(16):结构体排序

课程大纲

  • 一、常见排序方法
    • [1. 桶排序](#1. 桶排序)
    • [2. 冒泡排序](#2. 冒泡排序)
    • [3. 选择排序](#3. 选择排序)
    • [4. 插入排序](#4. 插入排序)
  • 二、结构体排序
    • [1. 融入实际](#1. 融入实际)
    • [2. 认识结构体](#2. 认识结构体)
      • [2.1 概念](#2.1 概念)
      • [2.2 框架](#2.2 框架)
        • [2.2.1 存储](#2.2.1 存储)
        • [2.2.2 输入输出](#2.2.2 输入输出)
        • [2.2.3 结构体数组](#2.2.3 结构体数组)
        • [2.2.4 例题](#2.2.4 例题)
          • [2.2.4.1 结构体读写](#2.2.4.1 结构体读写)
          • [2.2.4.2 结构体交换](#2.2.4.2 结构体交换)
  • 三、sort函数
    • [1. 使用方法](#1. 使用方法)
    • [2. 固定格式](#2. 固定格式)
  • 四、结构体和sort函数
    • [1. 成绩排名](#1. 成绩排名)
    • [2. NOIP 09年真题 洛谷P1068](#2. NOIP 09年真题 洛谷P1068)

一、常见排序方法


我们以下面的序列为例,看一看桶排序、冒泡排序、选择排序、插入排序的排序过程。
< 5 , 2 , 7 , 1 , 4 > <5, 2, 7, 1, 4> <5,2,7,1,4>


1. 桶排序

借助 cnt[] 数组的下标进行存储,适用于正整数和集中数字的排序。

下标 元素
1 1
2 2
3
4 4
5 5
6
7 7
8
9

2. 冒泡排序

两两元素比较,每一轮找出最大数字冒到最后一个位置。

轮数 排序结果
1 5 2 1 4 7
2 2 1 4 5 7
3 1 2 4 5 7

3. 选择排序

找最小值和区间的第一个元素交换。

轮数 排序结果
1 2 1 4 5 7
2 1 2 7 5 4
3 1 2 4 7 5
4 1 2 4 5 7

4. 插入排序

重复插入元素(扑克牌)。

轮数 排序结果
1 2 5 7 1 4
2 2 5 7 1 4
3 2 5 7 1 4
4 1 2 5 7 4
5 1 2 4 5 7

二、结构体排序

1. 融入实际

姓名 金牌 银牌 铜牌 总数
ml 6 5 8 19
lr 5 6 10 21
xc 5 5 4 14
hs 5 5 3 13
zl 3 6 7 16

如果按照原来的思想,需要进行 5 5 5 个数组,更占空间。

2. 认识结构体

2.1 概念

用户自定义一个数据类型,可以包含很多基础数据类型。

2.2 框架

2.2.1 存储
cpp 复制代码
struct Node // 结构体类型名后不带()
{
    char name[105]; // string类型最好用char[]数组,string可能导致不稳定
    int gold; // 数据类型 + 名称
    int silver;
    int copper;
    int sum;
}score; // 一定记得加分号
Node score = {"ml", 6, 5, 8, 19}; // 存储数据
2.2.2 输入输出
cpp 复制代码
cin >> score.name >> score.gold >> ...;
cout << score.gold; // 输出金牌数
2.2.3 结构体数组
cpp 复制代码
Node nodes[105];

这样可以让一组数据实现交换。

cpp 复制代码
swap(nodes[1], nodes[3]);

或者一个数据。

cpp 复制代码
swap(nodes[1].gold, nodes[3].gold);
2.2.4 例题
2.2.4.1 结构体读写

要求:第一行输入n,接下来n行输入一个名字+一个年龄,要求输出对应名字和对应的

cpp 复制代码
#include <iostream>
using namespace std;

int n;
struct Node
{
	char name[55];
	int age;
}people;

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> people.name >> people.age;
		cout << people.name << "年龄为" << people.age << endl;
	}
	return 0;
}

运行结果:

cpp 复制代码
[IN]
2
Andy 15
Anne 14

[OUT]
Andy年龄为15
Anne年龄为14
2.2.4.2 结构体交换

要求:第一行输入n表示人数,k和m表示对应需要交换的数组下标。

cpp 复制代码
#include <iostream>
using namespace std;

int n, k, m;
struct Node
{
	char chn[1005];
	char eng[1005];
	int grade;
	double high;
}stu[1005];

int main()
{
	cin >> n >> k >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> stu[i].chn >> stu[i].eng >> stu[i].grade >> stu[i].high;
	}
	swap(stu[k], stu[m]);
	for (int i = 1; i <= n; i++)
	{
		cout << stu[i].chn << " " << stu[i].eng << " " << stu[i].grade << " " << stu[i].high << endl;
	}
	return 0;
}

三、sort函数

1. 使用方法

cpp 复制代码
#include <iostream>
#include <algorithm> // 必须导入算法头文件
using namespace std;

int main()
{
    int a[10] = {10, 9, 8, 3, 4, 5, 7, 2, 6, 1};
    sort(a+2, a+8);
    for (int i = 0; i <= 9; i++)
    {
        cout << a[i] << " ";
    }
    return 0;
}

sort() 函数中,第一个参数 + 的是多少就是起始排序的下标;第二个参数 + 的是多少就是种植排序的下标 − 1 -1 −1 。sort() 默认会进行升序排序,要使用降序排序,则应该使用:

cpp 复制代码
// 方法1: 运用某些朝纲的东西
sort(a, a+5, greater<int>());

// 方法2: 自己定义比较规则
bool cmp(int a, int b)
{
    return a > b; // 降序
    // return a < b; 升序
}
sort(a, a+5, cmp);

2. 固定格式

使用前需要添加头文件:

cpp 复制代码
#include <algorithm>

使用格式:

cpp 复制代码
sort(数组 + 起始下标, 数组 + 终止下标 + 1)

四、结构体和sort函数

1. 成绩排名

题目描述

综合测评结束啦,现在语文数学成绩都出来了。我们再来排个序,排序规则如下:

语文成绩高的排在前面;

如果语文成绩一样,数学成绩高的排前面;

如果语文成绩和数学成绩都一样,按学号从小到大排序。

请你写代码输出一下排序结果吧
输入描述

输入有 n + 1 行,第一行是一个整数 n (0 < n < 30),为学生总人数;

接下来的 n 行中,每一行有三个整数,分别为学号 id(0 < id < 100),语文成绩 ch (0 < ch <= 100),数学成绩 ma(0 < ma <= 100),每个人的学号一定不同

输出描述

输出有 n 行,每行有学号、语文成绩和数学成绩,用空格隔开,按题目要求排序

样例1

输入

2
18 90 95
12 90 95

输出

12 90 95
18 90 95

样例2

输入

3
10 90 95
24 99 60
34 90 97

输出

24 99 60
34 90 97
10 90 95

【参考程序】

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

int n;

struct Node
{
	int id, chn, mth;
}stu[35];

bool cmp(Node a, Node b)
{
	if (a.chn != b.chn)
	{
		return a.chn > b.chn;
	}
	else if (a.mth != b.mth)
	{
		return a.mth > b.mth;
	}
	else
	{
		return a.id < b.id;
	}
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> stu[i].id >> stu[i].chn >> stu[i].mth;
	}
	sort(stu+1, stu+n+1, cmp);
	for (int i = 1; i <= n; i++)
	{
		cout << stu[i].id << " " << stu[i].chn << " " << stu[i].mth << endl;
	}
	return 0;
}

我们在书写 cmp() 函数的时候,传入的参数可能是 int 类型或者我们自定义的 Node 类型。int 类型可以调换一维数组的元素,Node 类型可以调换二维数组的一维数组。

2. NOIP 09年真题 洛谷P1068

问题描述

世博会志愿者的选拔工作正在A 市如火如荼的进行。为了选拔最合适的人才,A 市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的150%划定,即如果计划录取m名志愿者,则面试分数线为排名第m*150%(向下取整)名的选手的分数,而最终进入面试的选手为笔试成绩不低于面试分数线的所有选手。

现在就请你编写程序划定面试分数线,并输出所有进入面试的选手的报名号和笔试成绩。

输入格式

第一行,两个整数n,m(5 ≤ n ≤ 5000,3 ≤ m ≤ n),中间用一个空格隔开,其中n 表示报名参加笔试的选手总数,m 表示计划录取的志愿者人数。输入数据保证m*150%向下取整后小于等于n。第二行到第n+1 行,每行包括两个整数,中间用一个空格隔开,分别是选手的报名号k(1000 ≤ k ≤ 9999)和该选手的笔试成绩s(1 ≤ s ≤ 100)。数据保证选手的报名号各不相同。

输出格式

第一行,有两个整数,用一个空格隔开,第一个整数表示面试分数线;第二个整数为进入面试的选手的实际人数。从第二行开始,每行包含两个整数,中间用一个空格隔开,分别表示进入面试的选手的报名号和笔试成绩,按照笔试成绩从高到低输出,如果成绩相同,则按报名号由小到大的顺序输出。

样例1

输入

6 3
1000 90
3239 88
2390 95
7231 84
1005 95
1001 88

输出

88 5
1005 95
2390 95
1000 90
1001 88
3239 88

提示

样例说明: m ∗ 150 % = 3 ∗ 150 % = 4.5 m*150% = 3*150% =4.5 m∗150%=3∗150%=4.5 ,向下取整后为 4 4 4 。保证 4 4 4 个人进入面试的分数线为 88 88 88 ,但因为 88 88 88 有重分,所以所有成绩大于等于 88 88 88 的选手都可以进入面试,故最终有 5 5 5 个人进入面试。

【参考代码】

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

int n, m, line, people;

struct Node
{
	int id, s; 
}ps[5005];

bool cmp(Node a, Node b)
{
	if (a.s != b.s)
	{
	    return a.s > b.s;
	}
	return a.id < b.id;
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> ps[i].id >> ps[i].s;
	}
	sort(ps+1, ps+n+1, cmp);
	people = (int)(m * 1.5);
	line = ps[people].s;
	while (ps[people+1].s == line)
	{
		people++;
	}
	cout << line << " " << people << endl;
	for (int i = 1; i <= people; i++)
	{
	    cout << ps[i].id << " " << ps[i].s << endl;
	}
	return 0;
}
相关推荐
南东山人3 小时前
一文说清:C和C++混合编程
c语言·c++
LNTON羚通3 小时前
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
算法·目标检测·音视频·监控·视频监控
哭泣的眼泪4085 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
Ysjt | 深5 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__5 小时前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
Microsoft Word6 小时前
c++基础语法
开发语言·c++·算法
天才在此6 小时前
汽车加油行驶问题-动态规划算法(已在洛谷AC)
算法·动态规划
一只小小汤圆6 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
legend_jz6 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法