You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中用qsort对多维数组按指定列排序的实现方法

按指定列索引排序二维数组的实现方案

问题背景

原实现代码如下:

#include<stdio.h>
#include<stdlib.h>
int comp(const void *a, const void *b) {
    return (((int*)a)[0] - ((int*)b)[0]);
}
int main() {
    int arr[][4] = {
        {4,0,5,2}, 
        {0,5,4,6}, 
        {4,5,6,6}
    };
    int ROWS = sizeof(arr)/sizeof(arr[0]);
    qsort(arr, ROWS, sizeof(arr[0]), comp);
    for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++){
        for(int j = 0; j < sizeof(arr[0])/sizeof(arr[0][0]); j++){
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
}

需求是根据用户指定的列索引对二维数组行排序,预期效果如下:

column index = 0
0 5 4 6 
4 0 5 2 
4 5 6 6

column index = 1
4 0 5 2 
0 5 4 6 
4 5 6 6

column index = 2
0 5 4 6 
4 0 5 2 
4 5 6 6

column index = 3
4 0 5 2 
0 5 4 6 
4 5 6 6 

疑问:是否需要为每个列索引写不同的比较器?能否动态传递排序索引给比较器?

解决方案

不需要写多个比较器,有两种实用方法实现动态传递列索引:

方法1:使用全局变量传递列索引

这是最直接的方案,通过全局变量让比较器函数获取当前要排序的列索引:

修改后的完整代码:

#include<stdio.h>
#include<stdlib.h>

// 全局变量存储要排序的列索引
int sort_column;

int comp(const void *a, const void *b) {
    // 用全局变量指定的列进行比较
    return ((*(int**)a)[sort_column] - (*(int**)b)[sort_column]);
}

int main() {
    int arr[][4] = {
        {4,0,5,2}, 
        {0,5,4,6}, 
        {4,5,6,6}
    };
    int ROWS = sizeof(arr)/sizeof(arr[0]);
    int COLS = sizeof(arr[0])/sizeof(arr[0][0]);
    
    // 示例:测试列索引0-3的排序效果
    for (sort_column = 0; sort_column < COLS; sort_column++) {
        printf("column index = %d\n", sort_column);
        // 每次排序前复制原数组,避免前一次排序影响结果
        int temp_arr[ROWS][COLS];
        for (int i = 0; i < ROWS; i++) {
            for (int j = 0; j < COLS; j++) {
                temp_arr[i][j] = arr[i][j];
            }
        }
        qsort(temp_arr, ROWS, sizeof(temp_arr[0]), comp);
        // 打印排序结果
        for(int i = 0; i < ROWS; i++){
            for(int j = 0; j < COLS; j++){
                printf("%d ", temp_arr[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

注意:全局变量的弊端是不适合多线程场景,单线程程序使用足够简单高效。

方法2:使用qsort_r(GNU扩展)实现上下文传递

如果编译器支持GNU扩展(比如GCC、MinGW),可以用qsort_r替代qsort,它允许直接传递上下文参数给比较器,无需全局变量,更健壮:

完整代码示例:

#include<stdio.h>
#include<stdlib.h>

// 比较器函数,额外接收上下文参数(列索引)
int comp_r(const void *a, const void *b, void *arg) {
    int col = *(int*)arg;
    return ((*(int**)a)[col] - (*(int**)b)[col]);
}

int main() {
    int arr[][4] = {
        {4,0,5,2}, 
        {0,5,4,6}, 
        {4,5,6,6}
    };
    int ROWS = sizeof(arr)/sizeof(arr[0]);
    int COLS = sizeof(arr[0])/sizeof(arr[0][0]);
    
    for (int col = 0; col < COLS; col++) {
        printf("column index = %d\n", col);
        int temp_arr[ROWS][COLS];
        for (int i = 0; i < ROWS; i++) {
            for (int j = 0; j < COLS; j++) {
                temp_arr[i][j] = arr[i][j];
            }
        }
        // 调用qsort_r,把列索引作为上下文参数传递
        qsort_r(temp_arr, ROWS, sizeof(temp_arr[0]), comp_r, &col);
        // 打印结果
        for(int i = 0; i < ROWS; i++){
            for(int j = 0; j < COLS; j++){
                printf("%d ", temp_arr[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

关键说明

  • 两种方法都实现了动态指定排序列,无需为每个列写单独的比较器。
  • 代码中加入临时数组复制,是为了每次排序都基于原始数组,避免前一次排序结果干扰后续测试。
  • 若数组元素可能为大数,比较器中的减法可能溢出,建议改用if-else判断返回值,更安全:
    int val_a = ((*(int**)a)[col]);
    int val_b = ((*(int**)b)[col]);
    if (val_a > val_b) return 1;
    else if (val_a < val_b) return -1;
    else return 0;
    

内容的提问来源于stack exchange,提问作者Bittu970

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:15:12