具有查找功能的优先级队列 - 最快的实现

时间:2010-10-20 02:24:05

标签: optimization types heap binary-tree priority-queue

我正在考虑实现一个具有附加要求的优先级队列,一个查找/搜索功能,它将判断一个项目是否在队列中的任何位置。所以函数将是:insert,del-min和find。

我不确定是否应该使用Heap或Self-balancing二进制搜索树。看来PQ通常用Heap实现,但我想知道使用二叉搜索树是否有任何优势,因为我还需要find函数。

此外,平均而言,我会做更多的插入而不是删除。我也在考虑d-ary heap。基本上,每一秒都很重要。

谢谢!

7 个答案:

答案 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)

带有min-heap属性的

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万个项目。

布隆过滤器有一些有趣的属性:

  • 如果布隆过滤器的答案是否定的,则100%可靠。
  • 如果答案是肯定的,您必须检查其他数据 结构,以确保该项目实际存在。
  • 确保选择好的哈希函数:)