题干要求:
QUESTION 7. Classify the elements in an integer array as odd or even 将一个整型数表中的元素按照奇数偶数归类
任务:将所有的奇数移动到偶数前面,并且奇偶数分别按照升序排序。
功能要求:
1)输入一组整数,以顺序结构存储。整数个数不小于20;
2)采用两种以上的算法实现奇、偶数归类。
3)采用两种以上算法实现排序**。**
需求分析与设计文档
- 考试排座痛点
监考老师常需按照固定规则(如“奇偶分区”“左右隔开”)快速排定一个合适的不容易作弊的座位,并希望一目了然地查看最终布局。 - 本系统目标
- 读取 ≥ 20 个整数(可视为考生编号)。
- 根据奇偶性分类,并分别升序排序。
- 将奇数与偶数映射到教室座位(左右或前后排,奇偶方位可选)。
- 扩展:支持手动输入、随机生成、CSV 批量导入,处理结果再导出 CSV,自动化并发文件导入后导出;提供算法交互界面以及字符串“伪UI”。
- 条件编译后支持算法可视化,以及性能报告
| 阶段 | 功能 | 关键要点 |
|---|---|---|
| 输入阶段 | - 手动输入 - 随机生成 - 多 CSV 文件批量导入 |
CSV 行列分隔符可配置,生成随机数,文件读写处理 |
| 归类阶段 | 三种算法任选(稳定额外数组、原地分区、双指针交换) | 时间 O(n),复杂度优化 |
| 排序阶段 | 两种算法任选(快速排序、堆排序) | 升序,各自独立 |
| 排座阶段 | - 左/右排或前/后排 - 奇数放左(前)或右(后) |
行列可设置,情况可设置 |
| 输出阶段 | - ASCII 座位图 - 奇偶各写 CSV |
字符串输出算法处理 |
| 对象 | 物理结构 | 说明 |
|---|---|---|
| raw[] | int 一维数组 | 原始顺序数据 |
| odd[] | 动态数组 | 归类后奇数序列 |
| even[] | 动态数组 | 归类后偶数序列 |
| Seat seatMap[R][C] | struct Seat 二维顺序表 | R 行 C 列,记录行列索引与编号 |
| CsvFile | 结构体封装 | 路径、分隔符、行列数 |
- DATASET:一次处理会话
- RAW → ODD / EVEN:奇偶划分
- ODD / EVEN → SEAT:根据排布策略映射
| 备选 | 访问特点 | 评估 |
|---|---|---|
| 链表 | 插入 O(1) 但随机访问差 | 不利于排序与随机索引 |
| 数组 | 顺序存储,随机访问 O(1) | 排序友好;内存连续 |
综上,采用一维数组存整数,二维数组存座位。
- 菜单模块
- 用户选择数据源、算法、排布方式。
- 数据采集模块
- load_manual()
- load_random()
- load_csv_list()
- 归类模块(Strategy pattern)
- classify_stable()
- classify_partition()
- classify_two_ptr()
- 排序模块(可并行调用)
- quick_sort_wrapper()
- heap_sort()
- 排座模块
- gen_seat_map(mode_lr_or_fb, odd_side)
- 可视化与导出模块(可视化可选)
- render_ascii() → 终端图
- write_csv(odd.csv, even.csv, seat.csv)
- 性能统计模块(可选编译)
- bench_once(strategyPair, n)
核心流程:
伪代码:主调度:
main():
dataset = load_data_choose()
classifier = choose_classifier()
sorter = choose_sort()
split = classifier(dataset.raw, dataset.n)
sorter(split.odd, split.n_odd)
sorter(split.even, split.n_even)
seatMap = gen_seat_map(split, cfg)
render_ascii(seatMap)
export_csv(split, seatMap)
===== SeatSorter =====
[1] 导入/生成数据
[2] 选择归类算法 (1 稳定 2 原地 3 双指针)
[3] 选择排序算法 (1 快排 2 堆排)
[4] 座位排布设置 (L/R or F/B, 奇数在哪侧)
[5] 排座并显示+导出
[6] 重设数据
[7] 批量文件数据自动化处理
[q] 退出
- 步骤可反复调整;只有按 v 才真正执行分类-排序-排座。
- 导出文件默认 odd.csv, even.csv, seat_map.csv。
- 批量文件自动化处理,会批量处理同源文件,将其自定义解析后处理完后写到新的文件中
| 名称 | 核心思想 | 时空复杂度 | 稳定性 |
|---|---|---|---|
| classify_stable | 两个缓冲区收集 | O(n) / O(n) | ✅ |
| classify_partition | 单指针扫描+交换 | O(n) / O(1) | ❌ |
| classify_two_ptr | 前后双指针对撞 | O(n) / O(1) | ❌ |
| classify_partition()流程图: |

伪代码:
classify_partition(arr, n):
pivot = 0
for i in 0..n-1:
if arr[i] odd:
swap(arr[i], arr[pivot])
pivot++
| 名称 | 思路 | 复杂度 | 额外空间 | 备注 |
|---|---|---|---|---|
| 快速排序 | 分治,三数取中 | O(n log n) 平均 | O(log n) | 不稳定 |
| 堆排序 | 最大堆下沉 | O(n log n) | O(1) | 不稳定 |
快速排序子流程图:
这也是字符串算法的一部分,又称ASCII码字符画。
- 外框
- 顶部和底部使用 +、- 构成边框,左右两侧使用 |
- 四角用 + 表示,水平边线用 -,垂直边线用 |
- 座位单元
- 固定宽度(如 4~5 字符),格式统一为 [NN],编号两位数字右对齐
- 数量按实际排数×列数决定
- 过道
- 用 || 或若干空格表示,不计入行列数字
- 如果需要多条过道,可按需要增设
- 朝向标注
- 在图形顶部或底部居中写 Front/Rear,指示当前视图的前后方向
- 左右侧标注
- 在最底行或最底部横线外注明 Left、Aisle、Right
- 奇偶分组
- 可根据需求将奇数座号放在左侧或右侧,示例通过交换左右两侧数据实现
+------------------------------------------+
| 考试排座示意(示例 1) |
+------------------------------------------+
| Front |
| [01] [03] [05] || [02] [04] [06] |
| [07] [09] [11] || [08] [10] [12] |
| [13] [15] [17] || [14] [16] [18] |
| [19] [21] [23] || [20] [22] [24] |
| Rear |
+------------------------------------------+
Left Aisle Right
- 4 排 6 列(左右各 3 列);
- 奇数 [01,03,…] 全部排在左侧,偶数在右侧;
- Front 在顶部,Rear 在底部。
+------------------------------------------+
| 考试排座示意(示例 2) |
+------------------------------------------+
| Rear |
| [02] [04] [06] || [01] [03] [05] |
| [08] [10] [12] || [07] [09] [11] |
| [14] [16] [18] || [13] [15] [17] |
| [20] [22] [24] || [19] [21] [23] |
| Front |
+------------------------------------------+
Left Aisle Right
- 4 排 6 列;
- 偶数在左侧,奇数在右侧;
- Front 在底部,Rear 在顶部。
+------------------------------+
| 考试排座示意(示例 3) |
+------------------------------+
| Front |
| [01] [03] [05] [07] [09] [11]|
| [02] [04] [06] [08] [10] [12]|
| Rear |
+------------------------------+
- 2 排 6 列,无过道;
- 奇数切在第一行,偶数第二行。
以此类推:要切换前后排只需上下翻转“Front/Rear”及对应座号分布;要切换奇数在左/右,只需左右交换两侧数据段;若需多通道或更多列数/排数,按以上规范扩展即可。
/* seat_sort.c —— 唯一源文件 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* -------- 常量与类型 -------- */
#define MAX_N 1024
#define MAX_R 32
#define MAX_C 32
/* typedef struct … 所有结构体 */
/* -------- 工具函数 -------- */
static int is_odd(int x, int k, int r);
/* I/O: load_manual, load_random, load_csv */
/* 归类: classify_stable, classify_partition, two_ptr */
/* 排序: quick_sort_wrapper, heap_sort */
/* 排座: gen_seat_map */
/* 输出: render_ascii, export_csv */
/* -------- 菜单与调度 -------- */
static void menu_loop(void);
/* main() 调用 menu_loop() */
- 使用 clock() 记录归类与排序耗时。重点在于与Excel表格自定义宏和函数进行对比,证明算法是有实际意义的,其相的优势明显。可视化处理是否正确仍需确定。
- 批量处理,高度并发能力验证,需要证明这个系统对于多文件导入的状况良好。
- 对不同文件解析处理的健壮性,以及该系统完备性和对用户友好性仍需验证,并适当做出相应改进。
- 算法创新:针对特定场景:比如排座的针对性垂直领域算法创新。在通用算法基础上进行细化与改进。
- 交互创新:批量设置文件名,颜色宏等功能有效提升交互方式与工作流效率,增加系统可用度
- 并发创新:批量自动化设置作为系统一大特点,可以针对线程(c++)进行优化,提高并发度,并增加系统稳固性,并发健壮性。
- 专用设备优化:经过网络上,权威机构调查,我们可以得知windows市占率较高,可以针对Windows AVX2指令集以及Windows线程接口等进行优化提高并发度与算法在特定机型(较新Windows设备上)的用户体验和重要的效率。


