【问题标题】:sorting 2-d array based on the first column根据第一列对二维数组进行排序
【发布时间】:2018-08-17 09:26:23
【问题描述】:

我有一个如下所示的temp2.dat 文件:

0.060493 1 0.5 1
1.596961 0 0.1 2
0.87758  1 0.3 1.5
0.165453 1 0   3
0.07085  1 0.3 4
0.125379 1 0.2 3
0.454202 1 0.2 2
0.373227 1 0.3 1
0.131486 1 0.3 3
0.867477 0 0.5 4
0.122609 0 0.8 9

现在我想在C 中编写函数,以升序对这 4 列进行排序,但仅基于第一列的值。我尝试修改以下代码,但失败了:

struct data_t
{
    double x;
    int y;
    double z;
    double k;
};

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;
    if(m->x == n->x)
        return m->y > n->y;
        return m->z > n->z;
        return m->k > n->k;
    return m->x > n->x;
}

有人可以帮我做这件事吗?预期结果应如下所示:

0.060493 1 0.5 1
0.07085  1 0.3 4
0.122609 0 0.8 9
0.125379 1 0.2 3
0.131486 1 0.3 3
................
0.87758  1 0.3 1.5
1.596961 0 0.1 2

【问题讨论】:

  • 您的compare 功能很奇怪。请查找一些可能是qsort 的示例,并注意测试浮点值是否相等。请发布显示问题的Minimal, Complete, and Verifiable example
  • return m->k > n->k;return m->x > n->x; 是没用的,它们永远无法到达,你只能从函数中返回 1 个对象。我强烈建议在您的if 语句中添加一些括号{ ... },以明确您想要的内容,或者至少更改缩进。你现在拥有的是误导性的。
  • @yano:非常感谢。下次我会注意这一点。

标签: c sorting qsort


【解决方案1】:

首先,在 C 语言中,如果您想在任何块中包含多个语句,则必须用 {} 将其包围。因此,您的最后 3 个 return 语句将永远无法到达(缩进对编译器无关紧要,仅对人类而言)。

其次,当您调用return 时,您的代码不会返回。因此,您可以使用嵌套的 ifs 来比较这些值,以防它们在某些列中相同。比如:

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;
    if(m->x == n->x) {
        if (m->y == n->y) {
            if (m->z == n->z) {
                return m->k > n->k;
            }
            return m->z > n->z;
        }
        return m->y > n->y;
    }
    return m->x > n->x;
}

【讨论】:

  • 我假设正确的逻辑是减去,而不是比较
  • 啊,我错过了 qsort 标签。只是从 OP 写的内容推断比较函数做了什么。
  • @BrunoEly:非常感谢!让我试试你的代码,看看它是否真的做了我想做的事。您是否使用上面给定的示例数据集进行了尝试?
  • 注意:这个compare() 足以与qsort() 一起使用,因为它也期望负返回值。
【解决方案2】:

试试这个比较功能

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;

    if(m->x != n->x)
        return (m->x > n->x) - (m->x < n->x);

    if(m->y != n->y)
        return m->y - n->y;

    if(m->z != n->z)
        return (m->z > n->z) - (m->z < n->z);

    if(m->k != n->k)
        return (m->k > n->k) - (m->x < n->k);

    return 0;
}

这将比较第一列x。如果x 在两个元素中相同,则移动到第二列y。如果第二列相同,则移动到第三列,依此类推。

我们想要两个值之间的差异。例如,m-&gt;y - n-&gt;y。比较函数应返回整数值 0、负数或正数。

比较double 的值时,我们不能使用m-&gt;x - n-&gt;x,因为compare 的返回值是int。我们改用比较函数。

测试

struct data_t
{
    double x;
    int y;
    double z;
    double k;
};

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;

    if(m->x != n->x)
        return (m->x > n->x) ? 1 : -1;

    if(m->y != n->y)
        return m->y - n->y;

    if(m->z != n->z)
        return (m->z > n->z) ? 1 : -1;

    if(m->k != n->k)
        return (m->k > n->k) ? 1 : -1;

    return 0;
}

int main(void)
{
    struct data_t data[] = 
    { 
        { 0.060493, 3, 0.4, 7 },//1st column is the same
        { 0.060493, 2, 0.5, 8 },
        { 0.060493, 1, 0.6, 9 },

        { 0.060493, 3, 0.3, 4 },//1st & 2nd columns are the same
        { 0.060493, 3, 0.2, 5 },
        { 0.060493, 3, 0.1, 6 },

        { 0.060493, 1, 0.5, 3 },//1st & 2nd & 3rd columns are the same
        { 0.060493, 1, 0.5, 2 },
        { 0.060493, 1, 0.5, 1 },

        { 0.122609, 0, 0.8, 9 },
        { 0.125379, 1, 0.2, 3 },
        { 0.131486, 1, 0.3, 3 },
    };

    int count = sizeof(data) / sizeof(data[0]);
    qsort(data, count, sizeof(data[0]), compare);

    for(int i = 0; i < count; i++)
    {
        printf("%.6f %d %.1f %.0f\n",
            data[i].x, data[i].y, data[i].z, data[i].k);
    }

    return 0;
}

输出:

0.060493 1 0.5 1
0.060493 1 0.5 2
0.060493 1 0.5 3
0.060493 1 0.6 9
0.060493 2 0.5 8
0.060493 3 0.1 6
0.060493 3 0.2 5
0.060493 3 0.3 4
0.060493 3 0.4 7
0.122609 0 0.8 9
0.125379 1 0.2 3
0.131486 1 0.3 3

【讨论】:

  • 非常感谢您的大力帮助!如果第一列不一样,每次compare() 函数都会自动将同一行但剩余列中的元素向下移动 1 行?
  • 我打印了输出,看起来不错。它正在排序第一列,然后是第二列等等。
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 2013-12-16
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
相关资源
最近更新 更多