如何在C语言中不将数字转换为字符串实现字典序排序?
在C语言中不转换字符串实现数字的字典序排序
嘿,这个需求我get到了——之前你尝试转成字符串做字典序排序,但现在想直接用数字操作来实现对吧?没问题,咱们来一步步搞定它。
先搞懂数字的字典序到底比什么
首先得明确:数字的字典序排序,本质上和把数字转成字符串后按字符顺序比较是一样的逻辑。比如:
- 比较12和119:转成字符串是"12"和"119",先比第一位都是1,第二位"2" vs "1",所以"119"更小,排在前面,对应数字就是119在12前面。
- 比较3和25:字符串"3" vs "25",第一位"3"比"2"大,所以25排在3前面。
核心就是从最高位开始逐位对比,短数字如果前几位和长数字的前缀一致,短数字排在前面(比如123和1234,123的字符串更短,前缀相同,所以123在前)。
不用字符串的实现思路:数值拼接比较
不用转字符串的话,我们可以用一个巧妙的方法:把两个数a和b分别拼接成a后接b、b后接a的两个大数字,然后比较这两个大数字的大小。比如:
- 对于a=12,b=119:拼接成12119(a+b)和11912(b+a),因为11912 < 12119,所以b应该排在a前面,正好符合字典序。
- 对于a=123,b=1234:拼接成1231234和1234123,前者更小,所以a排在b前面,正确。
这个方法的好处是完全用数值运算,不需要转字符串,而且逻辑简洁。
完整代码示例
下面是具体的C语言实现,我们用qsort函数配合自定义的比较函数来完成排序:
#include <stdio.h> #include <stdlib.h> // 计算数字的位数(处理非负整数) int getDigitCount(long long num) { if (num == 0) return 1; int count = 0; while (num > 0) { count++; num /= 10; } return count; } // 计算10的n次方,用于拼接数字 long long powerOf10(int n) { long long result = 1; for (int i = 0; i < n; i++) { result *= 10; } return result; } // 自定义比较函数,用于qsort int compareLexicographic(const void *a, const void *b) { long long numA = *(const long long *)a; long long numB = *(const long long *)b; // 处理0的特殊情况(默认把0排在最前面,可按需调整) if (numA == 0) return -1; if (numB == 0) return 1; int lenA = getDigitCount(numA); int lenB = getDigitCount(numB); // 计算两种拼接后的数值 long long concatAB = numA * powerOf10(lenB) + numB; long long concatBA = numB * powerOf10(lenA) + numA; // 按拼接结果比较,返回对应排序规则 if (concatAB > concatBA) { return 1; // numA应该在numB后面 } else if (concatAB < concatBA) { return -1; // numA应该在numB前面 } else { return 0; // 两个数字字典序相同 } } int main() { long long nums[] = {12, 119, 3, 25, 2, 123, 1234}; int size = sizeof(nums) / sizeof(nums[0]); printf("排序前:"); for (int i = 0; i < size; i++) { printf("%lld ", nums[i]); } printf("\n"); qsort(nums, size, sizeof(long long), compareLexicographic); printf("排序后(字典序):"); for (int i = 0; i < size; i++) { printf("%lld ", nums[i]); } printf("\n"); return 0; }
关键点说明
- 为什么用
long long?因为拼接后的数字可能会很大,用int容易溢出,long long能处理更大的数值范围。如果你的数字特别大,甚至超过long long的范围,那可以改成逐位对比的方式,但大多数场景下long long足够用了。 - 0的处理逻辑:代码里默认把0排在最前面,你可以根据自己的需求修改这个规则。
qsort的用法:qsort会根据比较函数的返回值排序,返回-1表示第一个参数排在前面,1表示第二个参数排在前面,0表示相等。
运行上面的代码,输出会是:
排序前:12 119 3 25 2 123 1234 排序后(字典序):119 12 123 1234 2 25 3
完全符合字典序的预期!
内容的提问来源于stack exchange,提问作者Mehak Lakhanpal




