【问题标题】:How can I sort an array that depends on another, with qsort?如何使用 qsort 对依赖于另一个数组的数组进行排序?
【发布时间】:2019-04-18 20:07:20
【问题描述】:

例子:

degree =  [2,3,3,2,2,2]

vertex =  [1,2,3,4,5,6]

顶点 1 的度数为 2,顶点 2 的度数为 3,等等...

我需要这个解决方案vertex = [2,3,4,5,6,1]。我想使用度数来更改顶点。 (最后4个数字的顺序无关紧要(具有相同的度数。

我有更多的代码,但我认为这样就可以了。

谢谢!

typedef struct {
    u32 Orden;
    u32 Grado;
} ParGradoOrden;

int comGrado (const void * a, const void * b) {
    const u32 x = ((ParGradoOrden *) a)->Grado;
    const u32 y = ((ParGradoOrden *) b)->Grado;
    const u32 xx = ((ParGradoOrden *) a)->Orden;
    const u32 yy = ((ParGradoOrden *) b)->Orden;

    if (x < y)
        return 1;
    else if (x > y)
        return -1;

    if (xx < yy)
        return -1;
    else if (xx > yy)
        return 1;

    return 0;
}

qsort(G->vertices, n, sizeof(ParGradoOrden), comGrado);

Grafostv* ConstruccionDelGrafo()
{
    Grafostv* G = (Grafostv*)malloc(sizeof(Grafostv));
    u32 n = 0; //number of vertexs
    u32 m = 0; //number of edges
    u32 v = 0; //vertex name
    u32 w = 0; // vertex name
    int c = 0; //auxiliar char needed for fgetc function
    char prev = 'a';
    char edge[50] = {0};

    G->m = m;
    G->n = n;
    G->orden = (u32*)malloc(sizeof(u32) * n);
    G->grados = (u32*)malloc(sizeof(u32) * n);
    G->vertices = (u32*)malloc(sizeof(u32*) * n);

    for (u32 i = 0; i < 2*m; ++i)
        G->vecinos[i] = (u32*)malloc(sizeof(u32)*2);

    for (u32 i = 0; i < 2*m; i += 2)
    { 
        if(scanf(" %c %u %u",&prev, &v, &w) != 3 || prev != 'e')
        {
            free(G->color);
            free(G->orden);
            free(G->grados);
            return NULL;
        }
            G->vecinos[i][0] = v;
            G->vecinos[i][1] = w;
            G->vecinos[i+1][0] = w;
            G->vecinos[i+1][1] = v;
    } 
    qsort(G->vecinos, 2*m, 2*sizeof(u32), compare);
    G->vertices[0] = G->vecinos[0][0];
    copiarAVertice(G->vertices,G->vecinos,G->grados, G->indEnVecinos, 2*m);
    memset(G->visitados,0,n*sizeof(u32));
    memcpy(G->orden,G->vertices,n*sizeof(u32)); 
    G->max = Greedy(G);
    printf("terminé Greedy\n");
    return G;
}

【问题讨论】:

  • 您是否特别需要结果为[2,3,4,5,6,1],或者其他按程度降序排列的替代方案也可以,例如[2,3,1,4,5,6]
  • 您可以使用struct 的一个数组而不是两个数组。或者您可以使用顶点数组(传递给qsort)数据来索引度数数组,该数组仍然未排序。例如degree[ vertex[n] - 1]
  • 是的@JohnBollinger 就像你说的那样。它是相同的 [2,3,1,4,5,6] 或 [2,3,4,5,6,1] 等...

标签: c arrays sorting qsort


【解决方案1】:

我认为您希望 degree 数组保留其当前顺序。如果您想将它与顶点数组共同排序,那么您需要编写自己的排序例程; qsort 不会做这项工作。

当然,如果您不对degree 进行共同排序,那么从vertex 元素的 必须存在明确定义的1-1 映射degree 元素的索引,否则无法确定排序开始后哪个顶点的度数。您的示例似乎就是这种情况,顶点值比它们对应的 degree 元素的索引大一。

要根据degreevertex 数组进行排序,而不修改degree,提供给qsort 的比较函数必须能够通过文件范围变量访问degree。如果degree 本身未在文件范围内声明,那么您可以添加一个文件范围指针变量并将其设置为指向degree。当然,这有一个限制,您不能同时执行多个排序运行。

设置完成后,比较函数使用顶点编号访问数组中的顶点度数,并根据这些结果进行比较。看起来像这样:

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

typedef unsigned int u32;

u32 *vert_degree;

int compare_vertices(const void *v1, const void *v2) {
    u32 degree1 = vert_degree[*(const u32 *)v1 - 1];
    u32 degree2 = vert_degree[*(const u32 *)v2 - 1];
    if (degree1 > degree2) {
        return -1;
    } else if (degree1 < degree2) {
        return 1;
    } else {
        return 0;
    }
}

int main(void) {
    u32 degree[] = {2,3,3,2,2,2};
    u32 vertex[] = {1,2,3,4,5,6};

    vert_degree = degree;
    qsort(vertex, 6, sizeof(vertex[0]), compare_vertices);

    printf("%d", vertex[0]);
    for (int i = 1; i < 6; i++) {
        printf(", %d", vertex[i]);
    }
    putchar('\n');
    return 0;
}

输出:

2、3、1、4、5、6

如果您碰巧在基于 glibc 的系统(即 Linux)上,那么您还可以选择使用 qsort_r,它接受诸如 degree 数组之类的辅助数据,并将其传递给比较函数(因此必须接受一个附加参数)。这样可以避免依赖全局变量,但它是 glibc 特有的。

【讨论】:

  • 嗨,对于 unsigned int,比较不正确。我该如何解决?在v1 -1 v2 -1 是问题所在,不知道如何解决它
  • 你需要更具体地说明你认为它有什么问题,@MarcosCerioni。请注意,没有v1 - 1v2 - 1 本身,因为减法的优先级低于v1v2 的强制转换和取消引用。无论如何,我强调减 1 的目的是将您的示例展示的从 1 开始的顶点数与 C 的从 0 开始的数组索引相匹配。如果您的示例不能以这种方式代表您的实际需求,那么当然需要进行调整。
  • 另外,如果您的实际数据被声明为其他类型,那么您当然需要正确匹配类型。
  • 是的@JohnBollinger,对不起。我有这个例子但不工作degree = [2,3,3,2,2,2] vertex = [0,2,3,4,5,6]
  • @MarcosCerioni,我已将示例代码修改为一个完整的程序,演示排序并输出结果。运行时,它会为我生成正确排序的结果。比较函数不变。
猜你喜欢
  • 2019-05-23
  • 2016-10-22
  • 1970-01-01
  • 2020-09-27
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 2015-09-16
相关资源
最近更新 更多