我仍然对STL中的优先级队列感到困惑。这是我想实现的目标,比如说:我有一个名为Record的结构,它包含一个字符串字和一个int计数器。例如:我有很多这些记录(在示例程序中,只有5个),现在我想保留前N个记录(在样本中,3)。
我现在知道我可以重载运算符<在Record中,将所有记录放在一个向量中,然后初始化priority_queue,如:
priority_queue< Record, vector<Record>, less<Record> > myQ (myVec.begin(),myVec.end());
但是,据我所知,控制矢量myVec的大小并不容易,因为它没有按我的意愿排序。
我真的不明白为什么以下情况不起作用:
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();
}
}
编辑: 感谢您的投入,现在我得到了它的工作。但是,如果有人能够解释为什么第一个版本的运算符&lt;重载工作,第二个(注释掉)将无法工作,并有很长的编译器错误列表。
friend bool operator< (const Record& lhs, const Record& rhs)
{
return lhs.count>rhs.count;
}
/*
bool operator<(const Record& rRecord)
{
return this->count>rRecord.count;
}
*/
答案 0 :(得分:7)
std::priority_queue
无法神奇地知道如何对元素进行排序。你必须告诉它如何这样做。这样做的方法是给priority_queue
一个函子类型,当用两个对象调用时,它返回第一个参数是否“小于”第二个,但是你想要定义它。该仿函数是priority_queue
的模板参数。
默认参数为std::less<type>
,这要求type
(您在队列中放置的内容)的重载operator<
。如果没有,那么你要么必须提供一个,要么你必须提供一个适当的比较函子。
例如:
struct Comparator
{
bool operator()(const Record& lhs, const Record& rhs)
{
return lhs.count>rhs.count;
}
};
std::priority_queue<Record, std::vector<Record>, Comparator> myQ;
仅在Record
上过载不起作用的原因是因为您没有告诉priority_queue
它是比较。此外,用于比较的类型需要是默认构造的,以便priority_queue
可以随意创建和销毁对象。
虽然说实话,我不知道你为什么不把它们放在std::set
中,如果你想对它们进行排序。或者只在项目的std::sort
上运行std::vector
。
答案 1 :(得分:3)
您的代码 有效,只做了两处小改动:
Record::operator<()
的定义,因为优先级队列的默认比较器需要它。bool operator<(const Record &) const
(请注意额外的const
),因为优先级队列必须使用对const
个对象的引用进行比较。 或者,在类定义之外将其声明为自由函数:
bool operator<(const Record &l, const Record &r) {return l.count > r.count;}
或定义自己的仿函数,并将其作为适当的模板参数提供:
struct CompareRecords
{
bool operator()(const Record &l, const Record &r) {return l.count > r.count;}
};
typedef priority_queue<Record, vector<Record>, CompareRecords> RecordQueue;