是否总是有必要使用动态内存分配来实现哈希表?

问题描述 投票:0回答:3

我已经在网上搜索了此内容,并询问了我的助教,但我没有得到非常可靠的答案。我正在测试用于插入和搜索数据的不同数据结构的性能。我正在测试的数据结构之一是哈希表。

我知道动态分配内存是有好处的,如果您不知道数组的结束大小,并且出于多种原因想要实现double数组。但是说我们知道数据量。在这种情况下,40,000个整数值。我是否需要在堆上动态分配数组,还是可以使用相同的功能并通过静态实例化堆栈来使用?我会做同样的事情,创建头文件,实现文件和main(),但不动态分配内存。

c++ data-structures hashtable implementation
3个回答
0
投票

好问题。您可以在没有动态内存分配的系统上实现malloc,只需将一个大的空表放在malloc.c内,然后处理掉其中的一部分,直到用完为止。 Free会将块插入其中,因此您可能永远不会用完。

一种相关的内存分配方式是通过frame分配器(有时是池分配器);之所以命名,是因为它可以访问N M个大小的对象,而不是真正的动态分配器(每个对象的大小都不同)。帧分配器很棒,因为它们既快速又简单-一种罕见的组合。

因此,您当然可以在系统上工作而无需动态分配,但是您可能需要问自己为什么?您可以使用未指定的分配器来编写它,可以使用非常简单的框架分配器来实现,然后根据需要对其进行扩展。


0
投票

这实际上取决于您所说的“动态分配”。

典型的哈希表包含一个存储桶数组(或指向存储桶的指针数组)。每个存储桶都存储散列到同一散列的事物的集合。因此,给定一个要存储在哈希表中的40000 int集合,您需要为每个存储桶集合本身提供某种形式的动态分配。

如果使用动态分配,您的意思是“对malloc的调用”,那么您可以使用“ placement new”或您自己的内存管理的其他形式来管理哈希表本身,存储桶集合,每个单独的存储桶集合的内存。您将计算实现哈希表所需的内存量,再加上存储桶的集合,再加上最大存储桶数(最坏情况是每个存储桶一个条目,则为40000),这是最坏的情况。您仍然需要管理分配桶(因此需要“动态分配”),并且由于它们没有足够的空间来放置它们,因此您需要能够随着它们的生长而随机移动它们。只是您自己在管理分配,所以“动态分配”是否由您决定。


-1
投票

如果知道哈希表的最大(或固定)大小,则可以非常静态地对其进行分配。

动态分配的主要原因是在运行时改变大小,并能够在函数之间传递结构的所有权。例如(并且它根本不与哈希表绑定,因此我只使用通用结构):

Item *GetItem() {
    return new Item();
}

这将动态分配项目,并将其传递回调用方(以及所有权(管理其生命周期的责任))。避免动态分配的一种简单方法是:

Item *GetItem() {
    Item item;
    return &item;
}

不幸的是,该地址在返回时不可用,因为item当时不在范围内,因此您可以通过以下方式阻止这种情况的发生:

Item *GetItem() {
    static Item item;
    return &item;
}

即使从函数返回后仍保留该对象,但有一个限制,即该对象只能有一个副本。如果您尝试从该函数中获取两项,它们将是同一项,除非您意识到这一点,否则您可能会遇到错误。

因此,我想说,只要您只需要一个哈希表,就可以通过具有静态哈希表来避免动态内存分配。

当然,除了单拷贝限制外,它还要求您分配所需的最大空间。这不是一个[[不必要一个坏主意(特别是如果它是固定大小的),但是可能会导致效率低下。


无论如何,您可能会担心性能不必要。您可以轻松地预先以其最大/固定大小动态分配结构(而不​​是进行大量小的分配和取消分配)。由于每个哈希表实际上只发生一次(希望在分配之前在哈希表中有很多

use

),因此开销相对较小。并且它使您能够在程序中具有多个哈希表。
© www.soinside.com 2019 - 2024. All rights reserved.