在C中对混合数据类型的“数组”进行排序

时间:2013-09-17 08:29:44

标签: c

我有一个连续的内存块,其中前N个字节都包含A类型的对象,其余字节包含类型B的元素。例如,我可能有120个A类型的对象,后跟40个类型的对象B.

类型A和类型B都是具有不同大小的结构,但两者都有一个整数成员“index”,这是我想要排序的。基本上我想最终得到一个按索引排序的数组,我目前有一个按数据类型排序的数组。理想情况下,我希望最终按索引排序,然后按类型排序,所以类似

Index==1 elements | Index==2 elements | ... | Index==L elements
Type A   | Type B | Type A  |  Type B | ... | Type A| Type B

到目前为止,我唯一想到的是按索引分别对A类和B类块进行排序,然后使用memcopy来改变周围的东西,使它们看起来像上面一样。有更好的解决方案吗?

3 个答案:

答案 0 :(得分:2)

原始阵列是如何设置的?在同一个数组中混合使用不同类型似乎是一个坏主意。你需要将它们放在同一个数组中吗?

如果它们必须位于同一个数组中,您可能需要使用union。像

这样的东西
enum myType { A, B };
struct typeA { myType type; int key; ... data ... }
struct typeB { myType type; int key; ... data ... }
union myTypes { typeA myA; typeB myB }
myTypes data[128];

您现在可以使用C库中的qsort功能。

另一个选择是使用指向对象的单独指针数组,然后对辅助数组进行排序。你仍然需要在每个结构的开头有某种类型的字段。

答案 1 :(得分:1)

而不是建议的指针,你可能想要使用由类型和指针组成的结构(后者甚至是两个不同指针的联合)。在这种情况下,您可以轻松区分对象的类型 - 除非它们在同一位置具有ID字段。

假设你有

struct typeA {
    int whatever;
    int id;
}

struct typeB {
    double whatever;
    int id;
}

你被咬伤了,我必须按照我的说法去做:

struct typptr {
    enum type { typ_A, typ_B } type;
    union {
        struct typeA * Aptr;
        struct typeB * Bptr;
    }
}

int getID(struct typptr t)
{
    if (t.type == typ_A) {
        return (t.Aptr)->id * 2;
    } else {
        return (t.Bptr)->id * 2 + 1; // have B always sorted after A...
    }
}

通过这种方式,您可以轻松地为qsort编写cmp函数,以便对struct typptr进行排序。

如果类型“形状相似”,例如

struct typeA {
    int id;
    int whatever;
}

struct typeB {
    int id;
    double whatever;
}

即。在开始时有id字段,事情更容易(但我不知道这是否可移植),因为你总是可以转换为其中一个并读出id字段。所以你只需要一个指针数组就可以省略类型字段。

答案 2 :(得分:0)

您以后的评论中有重要信息 - 这些类型最初并未混合。 如果是这样,你可以单独在每个数组部分上运行一个排序阶段(快速排序或你想要的任何其他方法),然后在两个数组之间进行合并排序的最后阶段(假设你可以节省额外的空间)< / p>

仍然是NlogN + N = NlogN