- C++
桶排序C++
- @ 2026-7-4 15:30:41
零基础通俗易懂 桶排序完整教程(C++)
💡前置说明
适用人群:C++初学、信奥入门;只需掌握:数组+for循环 算法特点:数据范围固定且较小时,排序最快,比冒泡/选择排序高效很多 核心口诀:下标存数字,数组记次数,按序遍历输出
一、通俗原理(大白话)
- 把数组当做一排带编号的木桶
- 数组下标 = 木桶编号(对应要排序的数字)
- 数组数值 = 这个数字出现的次数
- 执行流程 ① 准备空木桶(定义数组,全局数组默认全部初始化为0,无需手动清零) ② 遍历所有数据,数字是几,就往几号桶丢一个球(对应下标计数+1) ③ 按顺序遍历木桶,读出桶内数据,天然形成有序序列
二、桶排序4大固定步骤(所有题目通用)
- 确定数据最大/最小值,定义合适大小的桶数组
- 读取全部数据,完成入桶计数
- 根据需求选择遍历顺序:升序/降序、去重/保留重复
- 遍历桶数组,输出排序结果
三、入门题型1:基础去重排序(年龄排序)
题目
输入n个年龄,从小到大排序,去掉重复数据输出 样例输入: 6 6 8 8 7 7 6 样例输出:6 7 8
逐行注释代码
#include<iostream> // 导入输入输出库,支持cin/cout
using namespace std; // 启用标准命名空间,省略std::前缀
int bucket[200]; // 定义桶数组,覆盖0-199年龄;全局变量默认全0
int main(){
int n, x; // n:数据总数,x:临时存储读取的数字
cin >> n; // 读取第一行:数据个数n
for(int i = 1; i <= n; i++){ // 循环n次,读取所有输入数据
cin >> x; // 读取单个年龄数据
bucket[x]++; // 核心代码:x号桶计数+1,记录数字出现
}
// 从小到大遍历桶,实现升序+去重
for(int i = 0; i <= 199; i++){
if(bucket[i] > 0){ // 判断:这个数字出现过
cout << i << " "; // 只输出一次,自动去重
}
}
return 0; // 程序正常结束
}
四、入门题型2:常规排序(保留重复数据)
题目
1~10000范围内正整数,全部排序,保留重复数字 样例输入: 6 87 84 91 90 99 95 样例输出:84 87 90 91 95 99
逐行注释代码
#include<iostream>
using namespace std;
int bucket[10005]; // 桶数组:覆盖1~10000全部数字
int main(){
int n, x;
cin >> n;
// 第一步:数据入桶计数
for(int i = 1; i <= n; i++){
cin >> x;
bucket[x]++;
}
// 第二步:升序遍历,保留重复数字
for(int i = 1; i <= 10000; i++){
// 数字出现几次,就打印几次
for(int j = 1; j <= bucket[i]; j++){
cout << i << " ";
}
}
return 0;
}
五、重难点:负数桶排序(偏移量用法)
核心知识点
数组下标不能是负数! 解决方法:加偏移量平移数据 例:数据范围 -1000 ~ 1000 → 全部+1000,映射为 0~2000合法下标 输出时减去偏移量,还原原始负数
题目
-1000~1000整数,从大到小降序排序,保留重复 样例输入: 6 87 -84 91 90 99 95 样例输出:99 95 91 90 87 -84
逐行注释代码
#include<iostream>
using namespace std;
const int OFFSET = 1000; // 定义偏移量常量,方便修改
int bucket[2001]; // 映射后下标范围:0~2000
int main(){
int n, x;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> x;
// 负数平移:原始数字+偏移量,转为正数下标
bucket[x + OFFSET]++;
}
// 倒序遍历桶:实现从大到小排序
for(int i = 2000; i >= 0; i--){
for(int j = 1; j <= bucket[i]; j++){
cout << i - OFFSET << " "; // 减去偏移量,还原原始数字
}
}
return 0;
}
六、拓展题型:桶排序计数查询
题目
输入n个分数,k次查询,输出每个分数的人数
逐行注释代码
#include<iostream>
using namespace std;
int bucket[101]; // 分数0~100,定义对应桶
int main(){
int n, k, score;
cin >> n >> k; // 读取数据总数、查询次数
for(int i = 1; i <= n; i++){
cin >> score;
bucket[score]++; // 统计每个分数人数
}
for(int i = 1; i <= k; i++){
cin >> score;
cout << bucket[score]<<" ";// 直接读取桶内结果输出
}
return 0;
}
七、必考总结+易错点(做题必看)
1. 三种输出模式区别
✅ 去重排序:单层循环 + if判断(有数据只输出1次) ✅ 保留重复排序:双层for循环(按次数重复输出) ✅ 降序排序:从大到小遍历桶下标
2. 高频易错点
- 局部数组不会自动清零!桶数组一律定义在main函数外面(全局),默认全0
- 出现负数必须加偏移量平移,不能直接当下标
- 桶排序只适合:数据范围小、数值为整数;数据跨度极大不能用
- 偏移量 = 数据最小值的绝对值
3. 算法优缺点
✅ 优点:代码简单、排序速度最快、自带去重+计数功能 ❌ 缺点:数据范围过大时,浪费内存,无法使用
0 条评论
目前还没有评论...