内存空间使用:链接列表指针与数组索引

时间:2017-05-20 23:23:54

标签: arrays pointers indexing data-structures linked-list

我正在学习链接列表,并且很好奇链接列表与具有相同元素的数组相比需要多少内存空间。 This page列出了以下链接列表的缺点:

  

列表的每个元素都需要指针的额外内存空间。

但是数组也必须为每个元素的索引使用内存,对吧?

我猜测索引会比指针占用更少的内存,但我很好奇我们会谈论什么样的比例。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

如果您将 value-types 用作数组元素,那么数组使用的存储空间就会减少。

我以C为例:

1。值数组:

struct Value {
    int x;
}

sizeof(Value) == 4 bytes (assuming zero overhead)

struct Value staticArray[10]; // will consume 10 * 4 == 40 bytes

2。如果它是一个指针数组,那么:

struct Value* staticArrayOfPointers[10];
for( size_t i = 0; i < sizeof(staticArrayOfPointers); i++ ) {
    staticArrayOfPointers[i] = calloc( sizeof(struct Value), 1 );
}
  • staticArrayOfPointers本身将消耗40个字节,因为指针长度为4个字节
  • 但是它还需要为每个索引分别分配每个元素,因此thgat的另外40个字节。
  • 总共80个字节。

3。如果它是使用内联值的链接列表,则使用堆:

struct Node {
    struct Value value; // stored inline, as a value, in the node, not elsewhere in memory
    Node* next;
}

sizeof(struct Node) == 8 bytes (assuming zero overhead and alignment, and 4-byte pointers)

struct Node* head = calloc( sizeof(struct Node), 1 ); // calloc zeroes memory
struct Node* current = head;
for( size_t i = 0; i < 10; i++ ) {
    current->next = calloc( sizeof(struct Node), 1 );
    current = current->next;
}

链接列表现在内存中至少有10 * 8(80)个字节,并且可能也是碎片,因为每个节点可能存在于内存中的不同位置。

4。如果它是使用指向值的链接列表(也使用堆):

struct Node2 {
    struct Value* valuePtr;
    Node* next;
}

sizeof(struct Node2) == 8 (as a pointer is also 4 bytes), but then add another 4 bytes for the `Value` instance located elsewhere:

struct Node2* head = calloc( sizeof(struct Node2), 1 ); // calloc zeroes memory
head->valuePtr = calloc( sizeof(struct Value), 1 );
struct Node2* current = head;
for( size_t i = 0; i < 10; i++ ) {
    current->next = calloc( sizeof(struct Node2), 1 );
    current->valuePtr = calloc( sizeof(struct Value), 1 );
    current = current->next;
}

此版本现在将消耗10 * ( 8 + 4 ) == 120个字节,但随着更多分配的进行,碎片化的可能性也会增加。

总结:

  • 值数组:n * sizeof(Element)
  • 指向值的指针数组:n * ( sizeof(Element*) + sizeof(Element) )
  • 值的链接列表:n * ( sizeof(Element) + sizeof(Node*) )
  • 指向值的链接列表:n * ( sizeof(Element*) + sizeof(Element) + sizeof(Node*) )

注意事项:

  • 这取决于语言。如果它是一种像C或C ++这样的语言可以完全控制内存,那么你可以使用上述任何一种方法。
  • 如果是Java,那么只有原始类型(intdouble,而不是string)是值类型,所有其他类型都是&#34;参考类型&#34;并在内部使用指针,但因为它是一个GC环境,你不会遭受致命的内存碎片......希望如此。
  • 如果它是C#或Swift,你可以在其中拥有值类型(struct vs class),那么你可以使用所有4个选项,但指针本身不会被暴露。< / LI>
  • JavaScript抽象出内部表示 - 所以你认为一个简单的Number值数组可能在内部是一个哈希映射或一个向量(虽然它的行为会相同)。