C++代码无法按数字出现次数排序,求问题排查与修正
问题需求
给定若干自然数,将这些数字十进制表示中出现的所有数字按出现次数升序排列;若出现次数相同,则数字较小的优先。
示例
输入:
5 124 229 1322 4 534
输出:
5 9 1 3 4 2
我的代码(无法实现预期排序)
#include <iostream> using namespace std; int v1[10],v2[10],lim,x,ok; int main() { cin>>lim; for(int i=1; i<=lim; i++) { cin>>x; while (x>0) { v1[x&10]++; v2[x%10]=x%10; x=x/10; } } while (!ok) { ok=1; for(int i=0; i<=lim; i++) { if(v1[i]>v1[i+1]) { swap (v1[i],v1[i+1]); swap (v2[i],v2[i+1]); ok=0; } } } ok=0; while (!ok) { ok=1; for(int i=0; i<lim; i++) { if(v2[i]>v2[i+1]) if(v1[i]==v1[i+1]) swap (v2[i],v2[i+1]); } } for (int i=0; i<=10; i++) { if(v2[i]!=0) cout<<v2[i]<<" "; } }
问题分析与修正
你的代码存在几个核心问题:
- 数字统计错误:
v1[x&10]++用位运算&10替代取余%10是错误的(比如x=12时,12&10得8,12%10得2),导致计数完全混乱,必须改成v1[x%10]++。 - 排序范围错误:排序的对象是0-9这10个数字,你却用输入的自然数个数
lim作为循环边界,导致排序逻辑完全错位,循环范围应该固定为0到8(避免i+1越界)。 - 排序逻辑割裂:分开两次冒泡排序的方式无法保证「次数升序优先,次数相同则数字升序」的规则,应该一次排序同时满足两个条件。
- 输出逻辑缺陷:
v2[i]!=0会漏掉数字0(如果输入包含0),应该判断v1[i]>0(即该数字确实出现过)。
修正后的代码
#include <iostream> #include <algorithm> using namespace std; struct Digit { int num; // 数字本身 int count; // 出现次数 } digits[10]; int main() { int lim, x; cin >> lim; // 初始化数字与计数 for (int i = 0; i < 10; i++) { digits[i].num = i; digits[i].count = 0; } // 统计每个数字的出现次数 for (int i = 1; i <= lim; i++) { cin >> x; // 单独处理输入为0的情况 if (x == 0) { digits[0].count++; continue; } while (x > 0) { int d = x % 10; digits[d].count++; x /= 10; } } // 自定义排序:先按次数升序,次数相同则按数字升序 sort(digits, digits + 10, [](const Digit& a, const Digit& b) { if (a.count != b.count) { return a.count < b.count; } else { return a.num < b.num; } }); // 输出出现过的数字 for (int i = 0; i < 10; i++) { if (digits[i].count > 0) { cout << digits[i].num << " "; } } cout << endl; return 0; }
修正说明
- 用结构体绑定数字和出现次数,排序时逻辑更清晰,避免两个数组分离导致的同步错误。
- 使用标准库
sort搭配lambda表达式,直接实现需求中的双重排序规则,比冒泡排序高效且不易出错。 - 补充了输入为0的处理逻辑,避免遗漏数字0的统计。
- 输出时仅打印出现过的数字,逻辑准确。
内容的提问来源于stack exchange,提问作者ReiStefan
相关产品推荐
相关产品推荐

