使用 qsort 对结构指针数组进行排序

Posted

技术标签:

【中文标题】使用 qsort 对结构指针数组进行排序【英文标题】:Sorting an array of struct pointers using qsort 【发布时间】:2014-07-04 13:50:12 【问题描述】:

尝试对这个结构数组使用 qsort 时,我得到了奇怪的结果。

我有这个结构:

struct access_data
    int sector;
    int arrival_time;
    int checked;
    int processed;
;

我从一个文件构造了一个 access_data 指针数组,它们按到达时间排序,但我需要稍后按扇区对它们进行排序,所以我有以下内容:

int compare_data(const void* a, const void* b)
    if (((access_data*)a)->sector < ((access_data*)b)->sector)
        return 1;
    else if (((access_data*)a)->sector > ((access_data*)b)->sector)
        return -1;
    else
        return 0;


void scan(access_data* data[], int len, int sec_to_sec_seek)
    qsort(data, len, sizeof(access_data*), &compare_data);

    show_data(data, len);

show_data 只是打印数据,但我在示例输入中得到以下信息;再次,按到达时间排序:

data[0]: arrival_time: 7, sector: 3
data[1]: arrival_time: 6, sector: 8
data[2]: arrival_time: 5, sector: 6
data[3]: arrival_time: 4, sector: 5
data[4]: arrival_time: 3, sector: 12
data[5]: arrival_time: 2, sector: 10
data[6]: arrival_time: 1, sector: 1
data[7]: arrival_time: 0, sector: 2

它根本不是按扇区排序,而是按反向到达时间。我真的完全不知道可能导致这种行为的原因。

【问题讨论】:

请发minimal test-case。 【参考方案1】:

您的代码表明您实际上是在尝试对指向结构的指针数组进行排序。

在这种情况下,您缺少一个间接级别。你的方向也颠倒了。

您的 compare_data 例程可以对结构数组进行反向排序,但您希望根据指针指向的内容对指针数组进行排序。

int compare_pointed_to_data(const void* a, const void* b) 
    // a is a pointer into the array of pointers
    struct access_data *ptr_to_left_struct = *(access_data**)a;
    struct access_data *ptr_to_right_struct = *(access_data**)b;

    if ( ptr_to_left_struct->sector < ptr_to_right_struct->sector)
        return -1;
    else if (ptr_to_left_struct->sector > ptr_to_right_struct->sector)
        return 1;
    else
        return 0;

【讨论】:

非常感谢。这解决了我的问题。 :-)。啊,那是痛苦的。 这一切都解决了!【参考方案2】:

错误 1

printf("size=%d",sizeof(access_data*));

打印 4,预期:16。这是最大的问题:排序 8 乘以 4 字节,而不是 8 乘以 16。

怪事2

qsort() 需要一个指向数据的指针,但 scan() 接收一个指向数据的指针。建议修复:

void scan(access_data data[], int len, int sec_to_sec_seek)
    qsort(data, len, sizeof(access_data), &compare_data);
    show_data(data, len);

优化3

您的compare_data() 等于

int compare_data(const void* a, const void* b)
    return ((access_data*)b)->sector - ((access_data*)a)->sector;

我的完整工作计划:

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

struct access_data 
    int sector;
    int arrival_time;
    int checked;
    int processed;
;
typedef struct access_data access_data;
void show_data(access_data*data, int len) 
        printf("Showing size=%d",sizeof(access_data*));
        for(int i=0;i<len;i++) printf("data[%d]: arrival_time: %d, sector: %d\n",i,data[i].arrival_time,data[i].sector);


int compare_data(const void* a, const void* b)
        return ((access_data*)b)->sector - ((access_data*)a)->sector;

int compare_data1(const void* a, const void* b)
    if (((access_data*)a)->sector < ((access_data*)b)->sector)
        return 1;
    else if (((access_data*)a)->sector > ((access_data*)b)->sector)
        return -1;
    else
        return 0;


void scan(access_data data[], int len, int sec_to_sec_seek)
    qsort(data, len, sizeof(access_data), &compare_data);

    show_data(data, len);


int main() 
        printf("START\n");
        access_data data[8]=
                3,4,5,6,
                2,1,5,5,
                1,1,3,6,
                4,4,5,4,
                5,4,3,4,
                6,2,5,6,
                7,2,5,4,
                0,4,5,6
        ;
        scan(data,8,  0);

【讨论】:

OP 将指针数组传递给函数 scan()。假设他可以轻松更改部分代码是不正确的。 @self 在文本中他说“结构数组”。这就是我写的。我们没有看到他的代码。 无效扫描(access_data* data[]【参考方案3】:

这里的问题是你告诉 QSort 对一个指针数组进行排序,结果比较器中的参数是指向指针的指针。

int compare_data(const void* _a, const void* _b)
    access_data *a = *(access_data**)_a, *b = *(access_data**)_b;
    if ((a)->sector < (b)->sector)
        return 1;
    else if ((a)->sector > (b)->sector)
        return -1;
    else
        return 0;


void scan(access_data* data[], int len, int sec_to_sec_seek)
    qsort(data, len, sizeof(access_data*), &compare_data);

    show_data(data, len);

如果您还有任何问题,请告诉我

【讨论】:

以上是关于使用 qsort 对结构指针数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在C中对指向char的指针数组进行qsort?

C语言篇 + 指针进阶练习 + qsort模拟实现(回调函数思想) + 指针和数组笔试题

模拟qsort实现冒泡排序

字符串数组排序(C语言)(qsort库函数)

使用 qsort 进行错误排序 - C

qsort