You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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在前)。

不用字符串的实现思路:数值拼接比较

不用转字符串的话,我们可以用一个巧妙的方法:把两个数ab分别拼接成a后接bb后接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

火山引擎 最新活动