unordered_set与链表查找之间的性能比较

时间:2019-03-10 14:09:08

标签: c++

我正在将C文件转换为C ++。由于仍将通过C代码调用这些函数,因此我将整个文件放在extern“ C”块中。 该文件包含以下代码-

struct node{
    char* name;
    struct node* next;
};

static struct node* list;  //file scope

void insertInList(FILE*){
    read file line-by-line and add names present in file to the list
}
bool isNamePresent(char* name){
    //iterate through Linked-list & returnt true if present
}

现在,在我看来,可以通过使用unordered_set来提高'isNamePresent'的复杂性。但是,从客户使用情况来看,列表中通常输入的名称很少(有时只有1个)

Q1)那么,我还是应该更改代码以使用unordered_set吗?在性能或其他任何方面是否仍被认为是一个很好的变化?如果是,请解释原因?? 另外,在知道了一般使用模式的情况下,是否会在软件开发过程中考虑“如果用户在文件中输入十万个名称该怎么办”这样的场景?

Q2)我应该如何将集合写入文件中?用全局空间写的以下几行有什么区别?

static std::unordered_set<std::string> st;
vs 
namespace{
    static std::unordered_set<std::string> st;
}//anonymous namespace

第一个是用一些垃圾值初始化的吗?

1 个答案:

答案 0 :(得分:2)

通常,唯一真正了解哪种方法在您的应用程序方案中效果最好的唯一方法是评估每种方法在您的应用程序方案中的性能。话虽这么说,我只会选择unordered_set。我这样做的主要原因是可读性。 unordered_set<string>非常清楚地传达了您在这里所做的事情:存储一堆字符串以便跟踪一组元素并有效地检查给定的字符串是否属于该集合(因为这是您唯一要做的事情)确实可以与unordered_set一起使用)。另一方面,链表可用于许多目的,实现的集合不是很常见。必须从使用列表的方式推断出该列表的用途。

此外,尽管unordered_set不一定是人们可以想象的最有效的哈希表,但它并不算糟糕,搜索链接列表很可能会更糟。在某些情况下,当只有几个项目时,在std::vector之类的连续容器中进行线性搜索可能会带来性能上的优势,但之所以要这样做是因为以下事实:遍历连续的内存非常多在现代处理器上高效。链表通常不是连续的。即使列表项碰巧是以连续方式分配的,与通过普通vector进行迭代相比,仍然存在内存和运行时开销。与std::vector相比,链接列表的主要优点在于,列表支持O(1)时间复杂度的随机插入,并且如果列表被修改,则指向列表项的指针仍然有效。这些属性似乎都与您的情况无关。 unordered_set的平均插入时间复杂度为O(1)。并且它具有O(1)平均查找时间复杂度(与列表的O(n)比较)。虽然在unordered_set中进行的查找通常会涉及一些间接操作,但在链表中进行的查找几乎肯定会涉及更多的间接操作。

因此,如果要在此处选择,则选择应该最有可能在std::unordered_setstd::vector之间。除非您真的需要其中一个属性,否则只有链接列表才能为您提供属性(例如,修改容器时指向项目的指针保持有效;但是,在这种情况下,您可能还想考虑使用std::set而不是链接清单)。如果您不这样做,我会选择std::unordered_set。如果性能真的很关键(到目前为止,很可能没有给出一个简单的链表似乎效果很好):测量,比较,分析…

关于第二个问题:两者之间没有真正的区别

static std::unordered_set<std::string> st;

namespace {
    std::unordered_set<std::string> st;
}

这些只是使事物具有内部联系的两种不同方式。在C ++中,我将使用未命名的命名空间(注意:如果您已经在使用未命名的命名空间,则不需要static),因为它看起来更像C ++。 static通常用于制作静态局部变量和成员变量; static的这种特殊用法(用于使具有内部链接的全局变量)主要用于实现C兼容性……