Hao Chen

cighao@gmail.com

  • About ME
  • Archives
  • Exploring World
Search

Hao Chen

cighao@gmail.com

  • About ME
  • Archives
  • Exploring World

如何给数百万考生的成绩排序

2015-12-17

这个问题是在联系中科大的导师时被导师问到的,那个时候已经通过了中科大的免试研究生的面试,然后联系了一个导师,得知我人在合肥时让我去他办公室聊聊,其实大概就是了解下专业水平吧。问了很多问题,这是其中一个。虽然距离现在已经过去了好几个月,但是突然想到了这个问题,就想把它写下来。

下面来说说这个问题吧,忽略内存的问题,假设这些考试成绩是可以一次被装载进内存的。由于数据比较多,哪怕是利用快速排序算法,性能也不是很好。其实这个时候我们可以好好分析下问题,被排序的对象是分数,分析下分数的特征,分数都是整数而且范围都在 0-100 之间。其实这个时候就应该要联想到桶排序了,下面来解决下这个问题。

其实我们这里只需借助一个一维数组就可以解决这个问题。请确定你真的仔细想过再往下看哦。

首先我们需要申请一个大小为 101 的数组 int a[101]。OK 现在你已经有了 101 个变量,编号从 a[0]~a[100]。刚开始的时候,我们将 a[0]~a[100] 都初始化为 0,表示这些分数还都没有人得过。例如 a[0] 等于 0 就表示目前还没有人得过 0 分,同理 a[1]等于 0 就表示目前还没有人得过 1 分……a[100]等于 0 就表示目前还没有人得过 100 分。

下面我们开始遍历所有人的分数,例如第一个人得了80分,那么我们令 a[80]++,如果第二个得了90分,那么我们令 [90]++,…,依次遍历当一个人得了 i 分之后我们就令 a[i]++。

最后你发现没有,a[0]~a[100]中的数值其实就是 0 分到 100 分每个分数出现的次数。接下来,我们只需要将出现过的分数打印出来就可以了,出现几次就打印几次,a[0]为 0,表示“0”没有出现过,不打印。我们可以写出下面的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main(){
int a[101],i,j,t;
for(i=0;i<=100;i++)
a[i]=0; //初始化为0
for(i=1;i<=5;i++){ //循环读入5个数,
scanf("%d",&t); //把每一个数读到变量t中
a[t]++; //进行计数
}
for(i=0;i<=10;i++) //依次判断a[0]~a[100]
for(j=1;j<=a[i];j++) //出现了几次就打印几次
printf("%d ",i);
return 0;
}

这样基本只要一次遍历就可以完成排序了,时间复杂度为 O(n),比一般的排序算法快很多。我们进一步思考,如果我们要输出的不仅仅是分数还有学生信息呢,比如说从小到大输出所有学生的姓名和分数,那么这个时候也只要做一点小小的变动就好了。

我们用一个结构体去表示一个学生,如下:

1
2
3
4
5
typedef struct students{ 
char name[15];
unsigned int score;
students *next;
}student;

然后把所有学生信息放在一个链表中去存储。

接下来考虑排序过程中处理的问题,这个时候排序的数组就不能简单的用 int a[101] 了,我们这时候就要用一个 student 的指针数组 student * score[101] 。

排序的过程中,我们依次遍历所有的学生分数,假设某个学生的分数为 i ,那么就在 score[i] 的后面插入该学生的节点:

1
2
3
unsigned int s = q->score;	
q->next = score[s]->next;
score[s]->next = q;

遍历完所有的学生分数后,我们就会发现整个学生信息的存储结构就会发生一个很大的变化,之前是所有的学生节点连成一个链表。但是现在排序完后,所有相同分数的学生信息放在一个链表的里,这些链表的头节点又都放在数组里,数组的下标就是他们的分数。

完整的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef struct students{
char name[15];
unsigned int score;
students *next;
}student;

int main(){
//freopen("data.txt","r",stdin);
int i,n;
student *head = (student *)malloc(sizeof(student));
head->next = NULL;
student *p,*u;
p=head;
scanf("%d",&n); // 输入学生总人数
for(i=0;i<n;i++){
u = (student *)malloc(sizeof(student));
scanf("%s%d",u->name,&(u->score)); // 输入学生信息
p->next = u;
p=u;
}
p->next = NULL;
printf("排序之前:\n");
p=head->next;
while(p!=NULL){
printf("%s:%d\n",p->name,p->score); // 输出排序前的学生信息
p=p->next;
}
// sort
student * score[101]; // score[i] 表示分数位 i 的学生组成的链表的头节点
memset(score,NULL,sizeof(score));
p=head->next;
student * q;
while(p!=NULL){
q=p;
p=p->next;
unsigned int s = q->score;
if(score[s]==NULL){
score[s] = (student *)malloc(sizeof(student));
score[s]->next = NULL;
}
q->next = score[s]->next;
score[s]->next = q;
}
printf("排序之后:\n");
for(i=0;i<101;i++){
if(score[i]==NULL)
continue;
p=score[i]->next;
while(p!=NULL){
printf("%s:%d\n",p->name,p->score);
p=p->next;
}
}

return 0;
}

测试输入:

7
a 20
b 30
d 10
c 20
e 5
f 5
g 40

测试输出:

排序之前:
a:20
b:30
d:10
c:20
e:5
f:5
g:40
排序之后:
f:5
e:5
d:10
c:20
a:20
b:30
g:40

  • 算法
  • 排序

扫一扫,分享到微信

微信分享二维码
Ngrok: 一个提供内网到外网映射的工具
在 Hexo 中给文章添加目录

Related Issues not found

Please contact @cighao to initialize the comment

© 2025 Hao Chen
Hexo Theme Yilia by Litten
  • Search

tag:

  • Javascript
  • Web 前端
  • Matlab
  • 遗传算法
  • 算法
  • Hexo
  • 计算机
  • Linux IO
  • Cassandra
  • 数论
  • SSD
  • NVMe
  • Database
  • 论文阅读
  • Disksim
  • flashsim
  • Ubuntu
  • 画图
  • 信号处理
  • 黑客
  • Mysql
  • Python
  • 爬虫
  • 粒子群算法
  • 模拟退火算法
  • Neo4j
  • Ngrok
  • SPDK
  • RocksDB
  • Java
  • Matplotlib
  • openstack swift
  • 分布式存储
  • 对象存储
  • 学术
  • Tool
  • C语言
  • 正则表达式
  • 端口扫描
  • 二层规划
  • 排序
  • 随笔
  • Nodejs
  • Tools
  • 数据库

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 数据库中的热点行优化 (SIGMOD'21 Paper 解读)

    2022-02-28

    #Database#论文阅读

  • NVMe SSD中namespace的介绍和创建

    2020-04-12

    #SSD#NVMe

  • 快速搭建 L2TP VPN 服务器

    2019-11-20

    #计算机#Tool

  • SPDK 介绍(二):SPDK 相关博客

    2019-10-25

    #SPDK

  • SPDK 介绍(一):使用 FIO 测试 SPDK

    2019-10-23

    #SPDK

  • RocksDB 介绍(一):相关博客

    2019-10-22

    #RocksDB

  • Linux IO 相关资料

    2019-09-29

    #计算机#Linux IO

  • Cassandra 介绍(三):Commitlog 介绍(1)

    2019-09-26

    #Cassandra

  • Cassandra 介绍(二):Blogs

    2019-09-22

    #Cassandra

  • Cassandra 介绍(一):Install and test with YCSB

    2019-09-19

    #Cassandra

  • 阿里数据库内核月报(汇总)

    2019-09-03

    #数据库

  • Neo4j 介绍(五):使用 java 访问 neo4j

    2019-04-24

    #Neo4j

  • Neo4j 介绍(四):关于 neo4j 的一些博客

    2019-04-21

    #Neo4j

  • Neo4j 介绍(三):使用 python 访问 neo4j

    2019-04-21

    #Neo4j

  • Neo4j 介绍(二):main 函数

    2019-04-13

    #Neo4j

  • 日常遇到的一些小问题的解决方案

    2019-03-29

    #计算机#Tool

  • Neo4j 介绍(一):安装

    2019-03-21

    #Neo4j

  • matlab 画图(十): 分组和堆叠的条形图

    2019-01-13

    #Matlab#画图

  • 论文写作常用工具

    2018-11-20

    #Tools

  • Openstack Swift学习(八):配置ntp

    2018-09-29

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(七):ssbench 使用

    2018-09-29

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(六):服务启动源码分析

    2018-09-29

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(五):debug 总结

    2018-09-29

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(四):中间件

    2018-09-29

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(三):log 配置

    2018-09-22

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(二):相关文档

    2018-07-20

    #openstack swift#分布式存储#对象存储

  • Openstack Swift学习(一):安装

    2018-07-12

    #openstack swift#分布式存储#对象存储

  • 在 linux 上首次使用 SSD

    2017-03-20

    #SSD

  • disksim-3.0 with flashsim 源码分析(六):垃圾回收

    2017-02-27

    #SSD#Disksim#flashsim

  • disksim-3.0 with flashsim 源码分析(五):写操作

    2017-02-27

    #SSD#Disksim#flashsim

  • disksim-3.0 with flashsim 源码分析(四):初始化

    2017-02-27

    #SSD#Disksim#flashsim

  • disksim-3.0 with flashsim 源码分析(三):callFsim()函数介绍

    2017-02-21

    #SSD#Disksim#flashsim

  • disksim-3.0 with flashsim 源码分析(二):DFTL 中的 cache

    2016-12-10

    #SSD#Disksim#flashsim

  • disksim-3.0 with flashsim 源码分析(一):disksim-3.0 和 flashsim 的安装

    2016-12-06

    #SSD#Disksim#flashsim

  • flashsim 源码分析(五): flashsim 的初始化

    2016-11-22

    #SSD#flashsim

  • flashsim 源码分析(四): 总线上锁机制的实现

    2016-11-13

    #SSD#flashsim

  • flashsim 源码分析(三): 总线通道中的交叉

    2016-11-11

    #SSD#flashsim

  • flashsim 源码分析(二): flashsim 中的面向对象设计

    2016-11-09

    #SSD#flashsim

  • flashsim 源码分析(一):安装 flashsim

    2016-11-08

    #SSD#flashsim

  • 利用概率算法求解八皇后问题

    2016-10-20

    #算法

  • 回溯法求解八皇后问题

    2016-10-20

    #算法

  • 利用概率算法估算集合大小

    2016-10-17

    #算法

  • 神奇的卡特兰数

    2016-10-07

    #算法#数论

  • 论文阅读:基于闪存的缓冲区管理算法

    2016-08-23

    #SSD#论文阅读#学术

  • 论文阅读:针对闪存的成本感知的缓冲区管理策略(DASFAA 2015)

    2016-08-19

    #SSD#论文阅读#学术

  • 暴力破解 wifi 密码

    2016-08-04

    #黑客

  • 论文阅读:SSD内部多级并行性的探索和利用(TOC 2013)

    2016-07-20

    #SSD#论文阅读#学术

  • 论文阅读:SSD中基于PSO的缓冲区管理算法(ICITCS 2015)

    2016-07-19

    #SSD#论文阅读#学术

  • 利用二级指针删除链表节点

    2016-07-09

    #算法

  • 抓包获取简书的登录密码

    2016-07-07

    #黑客

  • disksim with ssdmodel 源码解析(二十二):读写和擦除时间的计算

    2016-06-28

    #SSD#Disksim

  • 求离散采样信号的波峰和波谷

    2016-05-31

    #信号处理

  • matlab 画图(九): 横坐标标签倾斜设置

    2016-05-13

    #Matlab#画图

  • matlab 画图(八): 双坐标绘图

    2016-04-29

    #Matlab#画图

  • matlab 画图(七): 扇形图

    2016-04-24

    #Matlab#画图

  • matlab 画图(六): 横向柱状图

    2016-04-20

    #Matlab#画图

  • matlab 画图(五): 垂直柱状图

    2016-04-17

    #Matlab#画图

  • matlab 画图(四): 句柄作图示例

    2016-04-16

    #Matlab#画图

  • disksim with ssdmodel 源码解析(二十一):warm up ssd

    2016-04-15

    #SSD#Disksim

  • matlab 画图(三): 图形句柄

    2016-04-14

    #Matlab#画图

  • matlab 画图(二): 基本作图技巧

    2016-04-13

    #Matlab#画图

  • disksim with ssdmodel 源码解析(二十):统计结果的提取

    2016-04-12

    #SSD#Disksim

  • matlab 画图(一): 线条样式设计

    2016-04-11

    #Matlab#画图

  • disksim with ssdmodel 源码解析(十九):ssd 的初始化

    2016-03-31

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十八):GC 分析(五)

    2016-03-30

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十七):GC 分析(四)

    2016-03-30

    #SSD#Disksim

  • SSD 编程学习笔记(一)

    2016-03-29

    #SSD

  • disksim with ssdmodel 源码解析(十六):GC 分析(三)

    2016-03-29

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十五):GC 分析(二)

    2016-03-27

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十四):ssd_activate_elem函数分析

    2016-03-24

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十三):如何兼容64位系统

    2016-03-23

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十二):写操作分析

    2016-03-23

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(十一):地址映射

    2016-03-23

    #SSD#Disksim

  • matplotlib 画图(四):text 和 label 的设置

    2016-03-22

    #画图#Matplotlib

  • disksim with ssdmodel 源码解析(十):GC分析(一)

    2016-03-19

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(九):syssim_driver 系统级接口(二)

    2016-03-19

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(八):syssim_driver 系统级接口(一)

    2016-03-19

    #SSD#Disksim

  • matplotlib 画图(三):线的连续与间断

    2016-03-19

    #画图#Matplotlib

  • disksim with ssdmodel 源码解析(七):block的组织形式

    2016-03-18

    #SSD#Disksim

  • matplotlib 画图(二):图形填充

    2016-03-17

    #画图#Matplotlib

  • disksim with ssdmodel 源码解析(六):disksim_setup_disksim

    2016-03-16

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(五):程序流程介绍

    2016-03-16

    #SSD#Disksim

  • matplotlib 画图(一):横向柱状图

    2016-03-16

    #画图#Matplotlib

  • 一种时间复杂度为 O(N) 整数排序算法

    2016-03-15

    #算法#排序

  • disksim with ssdmodel 源码解析(四):ssd_event_arrive 函数的介绍

    2016-03-13

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(三):初次使用介绍

    2016-03-12

    #SSD#Disksim

  • disksim with ssdmodel 源码解析(二):输入参数的介绍

    2016-03-06

    #SSD#Disksim

  • 在 Hexo 中给文章添加版权信息

    2016-03-01

    #Hexo

  • python中的爬虫神器 XPath 介绍

    2016-03-01

    #Python#爬虫

  • 程序员得长多高

    2016-02-26

    #Python#爬虫#随笔

  • Hexo 博客添加打赏功能

    2016-02-23

    #Hexo

  • Hexo 主题优化

    2016-02-14

    #Hexo

  • 利用 HttpClient 刷 CSDN 博客文章浏览量

    2016-02-04

    #Java

  • nodejs 中模块使用的介绍

    2016-01-10

    #Nodejs

  • 利用 javascript 实现回到顶部效果

    2016-01-09

    #Javascript#Web 前端

  • Ngrok: 一个提供内网到外网映射的工具

    2015-12-18

    #Ngrok

  • 如何给数百万考生的成绩排序

    2015-12-17

    #算法#排序

  • 在 Hexo 中给文章添加目录

    2015-12-13

    #Hexo

  • Java 动态加载类

    2015-12-06

    #Java

  • python 中安装 requests 模块

    2015-12-05

    #Python#爬虫

  • 利用模拟退火算法求解TSP问题

    2015-12-04

    #算法#模拟退火算法

  • 模拟退火算法简介

    2015-12-03

    #算法#模拟退火算法

  • 粒子群优化算法简介

    2015-11-30

    #算法#粒子群算法

  • Hexo yilia主题添加网站访客人数统计

    2015-11-30

    #Hexo

  • 利用粒子群算法求解非线性二层规划问题

    2015-11-07

    #算法#粒子群算法#二层规划

  • 遗传算法的 matlab 实现

    2015-11-03

    #Matlab#遗传算法#算法

  • 基于javascript实现的2048小游戏

    2015-11-02

    #Javascript#Web 前端

  • 随机生成正整数 1-n 的一个排列

    2015-10-11

    #算法#C语言

  • disksim with ssdmodel 源码解析(一):disksim及ssdmodel模块扩展的安装

    2015-09-09

    #SSD#Disksim#Ubuntu

  • 固态硬盘(SSD)原理及相关介绍

    2015-08-31

    #SSD

  • windows7下安装ubuntu及相关问题的解决方案

    2015-08-27

    #Ubuntu

  • python 正则表达式的使用

    2015-08-22

    #Python#爬虫#正则表达式

  • 基于 python socket 的端口扫描程序

    2015-03-29

    #Python#端口扫描

  • mysql windows 下zip安装

    2015-03-29

    #Mysql