为链表预分配内存

时间:2021-02-13 08:04:43

标签: c++ linked-list

在一次技术面试中,那家伙问我“他想为链表预先分配内存,就像我们可以为数组做的那样”,那么他会怎么做呢?
我从来没有觉得有必要,也没有遇到过这个想法!我主要用 C++ 编写代码,我的回答是“就像我们在 C++ 中使用新命令进行内存分配一样,例如 int *p = new int[10],我可以在其中分配 40 个字节的内存,我会为我的 Linked 做同样的事情列表,如 Node *p = new Node()[10] ,其中 Node 是我的链表类名,如下所示:

class Node{
 public:
  int data;
  Node *next;
};

".
然后他进一步跟进,你将如何实施这一点,考虑到空间不是问题,它真的能节省时间吗?我主要是摸索答案,然后他继续下一个问题。
但我现在真的很想知道我是否正确,一个关于它的工作/操作的小例子真的会有所帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

<块引用>

你将如何实施这个

我们当然可以在不实际存储数据的情况下创建节点。我们可以使用(链表的)构造函数来完成它。

class LinkedList {
public:
    LinkedList(int n)
    {
        pRootNode = new Node();
        Node* pTraveler = pRootNode;

        for(int i = 0; i < n; i++)
        {
            pTraveler->next = new Node();
            pTraveler = pTraveler->next;
        }
    }
<块引用>

我会为我的链表做同样的事情,比如 Node *p = new Node()[10]

这会给你一个节点数组。您还需要对其进行处理,以便前一个节点包含指向下一个节点的指针。

<块引用>

真的会节省时间吗

像这样的链表将改进插入,因为我们在插入新条目时不需要分配新节点(直到需要新节点)。但是链表的实例化需要很短的时间(相对而言),因为我们在构造函数中分配节点。

据说链表有 O(1) 次插入和删除,最坏的情况是 O(n) 次访问/查找时间。因此,在我看来,预分配几乎没有影响,因为无论如何您都会花费相同的时间来分配节点。

答案 1 :(得分:1)

面试问题一般不直接回答,希望你能缩小用例和需求的范围。

<块引用>

他想为链表预先分配内存,就像我们为数组所做的一样

如果这确实是问题,那么面试官要么是故意问错,要么是误导。并且数组(std::array 或 c 样式数组)不仅会为它们存储的类型分配内存,还会构造它们(至少对于非原始类型),因此重要的是要知道它是否是通用的列表或某些类型的专家列表。另一方面,std::vector 实际上预先分配了内存。

您通常希望尽量减少单个内存分配的数量,因为这些可能很昂贵。

<块引用>

我会为我的链表做同样的事情,比如 Node *p = new Node()[10]

您不想这样做,因为这已经为每个节点构造了由列表管理的类型。对于原语,这不会是什么大问题,但对于像 std::list 这样的通用列表来说,这将是可怕的失败。

<块引用>

然后他进一步跟进,考虑到空间不是问题,您将如何实施这一点,是否真的可以节省时间?

你会分配更大的内存块(类似于std::vector所做的),当一个元素存储在列表中时,你将使用placment new,在已经预- 分配的空间。

如果空间不是问题并且列表会预先分配空间,例如100 个元素,每 100 个存储对象将节省 99 个内存分配。您肯定需要增加一些成本来手动跟踪预分配空间的哪些部分是空闲的,哪些不是,但这可能比分配内存便宜。

这只是为列表预先分配内存的粗略想法。但问题缺少太多信息,无法以有意义的完整方式回答。

相关问题