我正在考虑实现一个具有附加要求的优先级队列,一个查找/搜索功能,它将判断一个项目是否在队列中的任何位置。所以函数将是:insert,del-min和find。
我不确定是否应该使用Heap或Self-balancing二进制搜索树。看来PQ通常用Heap实现,但我想知道使用二叉搜索树是否有任何优势,因为我还需要find函数。
此外,平均而言,我会做更多的插入而不是删除。我也在考虑d-ary heap。基本上,每一秒都很重要。
谢谢!
答案 0 :(得分:4)
为什么不能只使用优先级队列和集合?当您将某些内容排入队列时,可将其添加到集合中。当您将其出列时,将其从集合中删除。这样,该集将告诉您队列中是否有东西。
答案 1 :(得分:4)
如果你的查找操作相对不频繁(并且你的堆很小),我只是做一个线性搜索。如果它相对频繁,或者堆很大,请考虑使用单独的数据结构或对象标志来跟踪堆成员资格(进行“查找”测试)。外部索引的乐趣在于能够将对象放在任意数量的容器中。
如果通过“查找”你真的是“找到并修改”(我发现我经常需要删除独立于典型的插入/删除分钟的优先级队列的东西),下面是我用三种方法:
给定一个高速率的插入/删除分钟(100K / s的连续)和低速率找到-删除(例如1 / s)的在相当小工作组(500-1000)我做了线性搜索该元素然后以标准方式从树中删除它。
鉴于插入/删除率较高以及相当频繁的查找删除,我只是间接地将删除的对象标记为“不感兴趣”。实际的免费延期,直到对象正常出列。
给定一个小的std :: priority_queue(其具有插入/删除分钟以外没有访问方法)只有很少的元件和相当不频繁的缺失,我只是复制整个队列到一个临时的std ::向量和复制修改/所需部分返回队列。然后我哭着睡觉。
答案 2 :(得分:2)
如果您需要多个数据结构的好处,那么您可以在合成中使用它们。 例如,如果您需要优先级队列和二进制搜索树的好处,那么就可以对它们进行所需的操作。
如果是insert
,则将元素插入其中。
如果它是find
,那么您可以使用二叉搜索树找到该元素,如果找到它,则继续在优先级队列中找到它。
如果它是min
,那么首先从优先级队列中删除它,现在您知道它是哪个元素,然后您可以从二叉搜索树中删除它。
如果它是del
,那么首先在二叉搜索树中找到它并将其删除,然后继续在优先级队列中找到它并将其从那里删除。
假设二叉树的节点和优先级队列的节点是指向元素的指针。
答案 3 :(得分:0)
IIRC上的搜索/查找是O(n)
,而在树上是O(log(n))
,其他标准PQ操作是相同的。
堆只是通过某种常数因子在经验上更有效率,所以如果它是一个大的队列,树应该更好,如果它很小,你需要测试和分析。从理论上讲,这一切都很好,但是如果这些常数因素很大,那么对于足够小的数据集来说可能完全无关。
答案 4 :(得分:0)
Radix trees将提供您需要的属性。这实际上会为您的操作带来恒定的时间复杂性。例如,如果我们查看this Haskell implementation,您提到的所有三个操作都具有时间复杂度 O(min(n,W))。其中 n 是元素的数量, W 是int(32或64)中的位数。
答案 5 :(得分:0)
请检查此代码。我编写了这个程序,这是一个具有您所需功能的优先级队列。
1. Insert
2. Find
3. Delete
4. Show
你可以试试。它工作得很好。这里我将最小数升序添加到最大数。
我使用优先级队列默认函数通过 switch case 来做到这一点。
queue.push()
queue.pop()
queue.top()
queue.size()
C++ 代码:
#include<bits/stdc++.h>
#include <queue>
using namespace std;
void show_queue(
priority_queue<int, vector<int>, greater<int> > data)
{
priority_queue<int, vector<int>,greater<int> > myq = data;
while (!myq.empty()) {
cout << '\t' << myq.top();
myq.pop();
}
cout << '\n';
}
int main()
{
priority_queue<int, vector<int>,greater<int> > myp_queue;
while(1)
{
int choice;
cout<<"\nwhat do you want to do?"<<endl;
cout<<"1. Insert \n2. Find \n3. Delete \n4. Show Queue \n\nchoice your option from above: ";
cin>>choice;
switch(choice)
{
case 1:
int n;
cout<<"Enter the value: " ;
cin>>n;// Option 2 => Insert
myp_queue.push(n);
break;
case 2:
if(!myp_queue.empty()){
cout<<"\n"<<myp_queue.top()<<" is the minimum number"<<endl; // Find the minimum number.
}else{
cout<<"\nEmpty Priority Queue"<<endl;
}
break;
case 3:
if(!myp_queue.empty()){
myp_queue.pop(); //Delete the minimum number from the queue
cout<<"\nSuccessfully Deleted"<<endl;
}else{
cout<<"\nThere is no element to delete"<<endl;
}
break;
case 4:
if(!myp_queue.empty()){
show_queue(myp_queue); // Show full queue
}else{
cout<<"\nEmpty Priority Queue"<<endl;
}
break;
default:
cout<<"\nYou are terminated!!! \nYou entered wrong input.\n"<<endl;
}
}
return 0;
}
答案 6 :(得分:-1)
将您的数据存储在您测试过的最快容器中,并使用bloom过滤器测试容器中是否有东西。
我在之前的项目中使用哈希表匹配了一个布隆过滤器,它在哈希表上加了400倍,平均大约有1万个项目。
布隆过滤器有一些有趣的属性: