简体   繁体   English

STL优先级队列的初始化

[英]initialization for STL priority queue

I'm still confused about priority queue in STL. 我仍然对STL中的优先级队列感到困惑。 Here is the objective I wanna achieve, say: I have a structure called Record, which contains a string word and a int counter. 我要达到的目标是这样的:我有一个称为Record的结构,其中包含一个字符串单词和一个int计数器。 For example: I have many records of these (in the sample program, only 5), now I want to keep top N records(in sample, 3). 例如:我有很多这些记录(在示例程序中只有5条),现在我想保留前N条记录(在示例3中)。

I know now that I could overload operator < in Record, and put all records in a vector, and then initialize the priority_queue like: 我现在知道我可以在Record中重载运算符<,并将所有记录放入向量中,然后像下面那样初始化priority_queue:

priority_queue< Record, vector<Record>, less<Record> > myQ (myVec.begin(),myVec.end());

However, as I understood, it's not easy to control the size of vector myVec because it's not sorted as I wanted. 但是,据我了解,控制向量myVec的大小并不容易,因为它没有按我的意愿排序。

I really don't understand why the following can not work: 我真的不明白为什么下面的方法不起作用:

struct Record
{
    string word;
    int count;
    Record(string _word, int _count): word(_word), count(_count) { };
    /*
      bool operator<(const Record& rr)
      {
          return this->count>rr.count;
      }
    */
    bool operator() (const Record& lhs, const Record& rhs)
    {
        return lhs.count>rhs.count;
    }
};

void test_minHeap()
{
    priority_queue<Record> myQ;
    Record arr_rd[] = {Record("William", 8),
                       Record("Helen", 4),
                       Record("Peter", 81),
                       Record("Jack", 33),
                       Record("Jeff", 64)};
    for(int i = 0; i < 5; i++)
    {
        if(myQ.size() < 3)
        {
            myQ.push(arr_rd[i]);
        }
        else
        {
            if(myQ.top().count > arr_rd[i].count)
                continue;
            else
            {
                myQ.pop();
                myQ.push(arr_rd[i]);
            }
        }
    }

    while(!myQ.empty())
    {
        cout << myQ.top().word << "--" << myQ.top().count << endl;
        myQ.pop();
    }
}

Edit: Thanks for your input, now I got it working.However, I prefer if someone could explain why the first version of operator< overload works, the second one (commented out one) won't work and has a long list of compiler errors. 编辑:感谢您的输入,现在我可以使用它了,但是,如果有人可以解释为什么operator <重载的第一个版本有效,第二个(注释为一个)不起作用,并且编译器列表很长,我更喜欢错误。

friend bool operator< (const Record& lhs, const Record& rhs)
{
    return lhs.count>rhs.count;
}

/*
bool operator<(const Record& rRecord)
{
    return this->count>rRecord.count;
}
    */

std::priority_queue cannot magically know how to sort the elements. std::priority_queue无法神奇地知道如何对元素进行排序。 You must tell it how to do so. 您必须告诉它怎么做。 The way to do that is to give priority_queue a functor type which, when called with two objects, returns whether the first argument is "less than" the second, however you want to define that. 做到这一点的方法是给priority_queue一个仿函数类型,当用两个对象调用该仿函数类型时,它返回第一个参数是否小于第二个参数,但是您要定义它。 This functor is a template parameter to the priority_queue . 该函子是priority_queue的模板参数。

The default parameter is std::less<type> , which requires that type (what you're putting in the queue) has an overloaded operator< . 默认参数是std::less<type> ,它要求该type (您要放入队列中的类型)具有重载的operator< If it doesn't, then you either have to provide one or you have to provide a proper comparison functor. 如果不是,那么您要么必须提供一个,要么必须提供适当的比较函子。

For example: 例如:

struct Comparator
{
  bool operator()(const Record& lhs, const Record& rhs)
  {
    return lhs.count>rhs.count;
  }
};

std::priority_queue<Record, std::vector<Record>, Comparator> myQ;

The reason that doesn't work with just an overload on Record is because you didn't tell the priority_queue that it was the comparison. 不能仅对Record进行重载的原因是因为您没有告诉priority_queue这是比较。 Also, the type used for comparison needs to be default constructable, so that the priority_queue can create and destroy the objects at will. 同样,用于比较的类型必须是默认可构造的,以便priority_queue可以随意创建和销毁对象。

Though to be honest, I don't know why you don't just stick them in a std::set if you want to sort them. 虽然说实话,但我不知道您为什么不对它们进行排序,而不只是将它们放在std::set Or just run std::sort on the std::vector of items. 或者只在项目的std::vector上运行std::sort

Your code does work, with two small changes: 您的代码确实起作用,但有两个小的更改:

  • Uncomment the definition of Record::operator<() , since that's needed by the priority queue's default comparator. 取消注释Record::operator<()的定义,因为优先级队列的默认比较器需要此定义。
  • Change the declaration to bool operator<(const Record &) const (note the extra const ), since the priority queue has to compare using references to const objects. 将声明更改为bool operator<(const Record &) const (请注意额外的const ),因为优先级队列必须使用对const对象的引用进行比较。

Alternatively, declare it as a free function, outside the class definition: 或者,在类定义之外将其声明为自由函数:

bool operator<(const Record &l, const Record &r) {return l.count > r.count;}

or define your own functor, and provide that as the appropriate template argument: 或定义自己的函子,并将其提供为适当的模板参数:

struct CompareRecords
{
    bool operator()(const Record &l, const Record &r) {return l.count > r.count;}
};

typedef priority_queue<Record, vector<Record>, CompareRecords> RecordQueue;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM