如何对指向结构的指针的矢量进行排序

How to sort vector of pointer-to-struct

本文关键字:排序 指针 结构      更新时间:2023-10-16

我正在尝试对concurrent_vector类型进行排序,其中hits_object是:

struct hits_object{
        unsigned long int hash;
        int position;
};

这是我正在使用的代码:

concurrent_vector<hits_object*> hits;
for(i=0;...){
    hits_object *obj=(hits_object*)malloc(sizeof(hits_object));
    obj->position=i;
    obj->hash=_prevHash[tid];
    hits[i]=obj;
}

现在我已经填充了一个名为hitsconcurrent_vector<hits_object*>

但我想对position属性上的concurrent_vector进行排序!!!

下面是一个典型命中对象内部的示例:

0 1106579628979812621
4237 1978650773053442200
512 3993899825106178560
4749 739461489314544830
1024 1629056397321528633
5261 593672691728388007
1536 5320457688954994196
5773 9017584181485751685
2048 4321435111178287982
6285 7119721556722067586
2560 7464213275487369093
6797 5363778283295017380
3072 255404511111217936
7309 5944699400741478979
3584 1069999863423687408
7821 3050974832468442286
4096 5230358938835592022
8333 5235649807131532071

我想根据第一列(类型为int的"位置")对其进行排序。第二列是unsigned long int类型的"hash"。

现在我尝试了以下操作:

std::sort(hits.begin(),hits.end(),compareByPosition);

其中compareByPosition定义为:

int compareByPosition(const void *elem1,const void *elem2 )
{
  return ((hits_object*)elem1)->position > ((hits_object*)elem2)->position? 1 : -1;
}

但当我放入std::sort(hits.begin(),hits.end(),compareByPosition); 行时,我不断出现分段错误

请帮忙!

您的比较函数需要返回布尔值0或1,而不是整数1或-1,并且它应该具有强类型签名:

bool compareByPosition(const hits_object *elem1, const hits_object *elem2 )
{
    return elem1->position < elem2->position;
}

您看到的错误是由于std::sort将comp函数返回的所有非零内容解释为true,这意味着左侧小于右侧。

注意:由于与sbi和Mike Seymour的对话,此答案经过了大量编辑。

int (*)(void*, void*)是C qsort()函数的比较器。在C++std::sort()中,比较器的原型是:

bool cmp(const hits_object* lhs, const hits_object* rhs)
{
    return lhs->position < rhs->position;
}
std::sort(hits.begin(), hits.end(), &cmp);

另一方面,您可以使用std::pair结构,默认情况下,它会比较其第一个字段:

typedef std::pair<int position, unsigned long int hash> hits_object;
// ...
std::sort(hits.begin(), hits.end());

在不知道concurrent_vector是什么的情况下,我无法确定是什么导致了分割错误。假设它类似于std::vector,则需要用hits.push_back(obj)而不是hits[i] = j填充它;不能使用[]访问向量末尾以外的元素,也不能访问空向量。

比较函数应该等效于a < b,返回一个布尔值;它不是一个C风格的比较函数,返回负数、正数或零。此外,由于sort是一个模板,因此不需要C样式的void *参数;所有内容都是强类型的:

bool compareByPosition(hits_object const * elem1, hits_object const * elem2) {
    return elem1->position < elem2->position;
}

此外,您通常不希望使用new(当然也绝不会使用malloc)来创建要存储在向量中的对象;最简单和最安全的容器是vector<hits_object>(以及一个将引用而不是指针作为参数的比较器)。如果您真的必须存储指针(因为对象的复制成本很高且不可移动,或者因为您需要多态性——这两种情况都不适用于您的示例),请使用智能指针(如std::unique_ptr),或者确保在使用完它们后使用delete

传递给std::sort()的第三个参数必须具有类似于operator<():的签名和语义

bool is_smaller_position(const hits_object* lhs, const hits_object* rhs)
{
  return lhs->position < rhs->position;
}

将指针存储在向量中时,不能重载operator<(),因为对于所有内置类型,小于都是固定的。


附带说明:不要在C++中使用malloc(),而是使用new。此外,我想知道为什么不使用对象,而不是指针。最后,如果concurrent_vectorstd::vector类似,则需要显式地使其扩展以容纳新对象。这就是你的代码的样子:

concurrent_vector<hits_object*> hits;
for(i=0;...){
    hits_object obj;
    obj.position=i;
    obj.hash=_prevHash[tid];
    hits.push_back(obj);
}

这看起来不对:

for(i=0;...){
    hits_object *obj=(hits_object*)malloc(sizeof(hits_object));
    obj->position=i;
    obj->hash=_prevHash[tid];
    hits[i]=obj;
}

在这里,您已经根据"i"对数组进行了排序,因为您将位置设置为i,它也将成为命中的索引!

以及为什么使用malloc,应该使用new(/delete)。然后,您可以为结构创建一个简单的构造函数来初始化hits_object

例如

struct hits_object
{
   int position;
   unsigned int hash;
   hits_object( int p, unsigned int h ) : position(p), hash(h) {;}
};

然后稍后写入

hits_object* obj = new hits_object( i, _prevHash[tid] );

甚至

hits.push_back(  new hits_object( i, _prevHash[tid] ) );

最后,您的比较函数应该使用与其参数的矢量相同的数据类型

bool cmp( hits_object* p1, hits_object* p2 )
{
  return p1->position < p2->position;
}

您可以向std::sort添加Lambda而不是函数。

struct test
{
    int x;
};
std::vector<test> tests;
std::sort(tests.begin(), tests.end(),
    [](const test* a, const test* b) 
    { 
        return a->x < b->x; 
    });