Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 内存空间使用:链表指针与数组索引_Arrays_Pointers_Indexing_Data Structures_Linked List - Fatal编程技术网

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

Arrays 内存空间使用:链表指针与数组索引,arrays,pointers,indexing,data-structures,linked-list,Arrays,Pointers,Indexing,Data Structures,Linked List,我正在学习链表,很好奇链表与具有相同元素的数组相比需要多少内存空间。列出了以下链接列表的缺点: 列表中的每个元素都需要为指针提供额外的内存空间 但是数组也必须为每个元素的索引使用内存,对吗 我猜索引比指针占用的内存要少,但我很好奇我们将讨论什么样的比率。有什么想法吗 如果使用值类型作为数组元素,那么数组使用的存储空间会更少 我将以C为例: 1.值数组: 2.如果是指针数组,则: 链表现在在内存中至少有10*8(80)个字节,并且也可能是碎片,因为每个节点可能存在于内存中的不同位置 4.如果是使用

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

列表中的每个元素都需要为指针提供额外的内存空间

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

我猜索引比指针占用的内存要少,但我很好奇我们将讨论什么样的比率。有什么想法吗

如果使用值类型作为数组元素,那么数组使用的存储空间会更少

我将以C为例:

1.值数组: 2.如果是指针数组,则: 链表现在在内存中至少有
10*8
(80)个字节,并且也可能是碎片,因为每个节点可能存在于内存中的不同位置

4.如果是使用值指针的链表(也使用堆):
struct节点2{
结构值*valuePtr;
节点*下一步;
}
sizeof(struct Node2)==8(指针也是4个字节),但随后为位于别处的“Value”实例添加另外4个字节:
struct Node2*head=calloc(sizeof(struct Node2),1);//calloc零内存
head->valuePtr=calloc(sizeof(结构值),1);
结构节点2*当前=头部;
对于(大小i=0;i<10;i++){
当前->下一步=calloc(sizeof(struct Node2),1);
当前->值ptr=calloc(sizeof(struct Value),1);
当前=当前->下一步;
}
这个版本现在将消耗
10*(8+4)==120
字节,但是随着分配的增加,碎片化的可能性也会增加

总之:
  • 值数组:
    n*sizeof(元素)
  • 指向值的指针数组:
    n*(sizeof(Element*)+sizeof(Element))
  • 值的链接列表:
    n*(sizeof(元素)+sizeof(节点*)
  • 指向值的指针的链接列表:
    n*(sizeof(Element*)+sizeof(Element)+sizeof(Node*))
注意事项:
  • 这取决于语言。如果它是一种C语言或C++语言,它可以完全控制内存,那么你可以使用以上任何方法。
  • 如果是Java,那么只有原语类型(
    int
    double
    ,但不是
    string
    )是值类型,所有其他类型都是“引用类型”,并在内部使用指针,但因为它是GC环境,所以不会出现致命的内存碎片。。。希望如此
  • 如果是C#或Swift,其中可以有值类型(
    struct
    vs
    class
    ),则可以使用所有4个选项,但指针本身不会公开
  • JavaScript将内部表示抽象出来——因此您认为是一个简单的
    Number
    值数组,在内部可以是一个哈希映射或一个向量(尽管其行为相同)
如果使用值类型作为数组元素,那么数组使用的存储空间会更少

我将以C为例:

1.值数组: 2.如果是指针数组,则: 链表现在在内存中至少有
10*8
(80)个字节,并且也可能是碎片,因为每个节点可能存在于内存中的不同位置

4.如果是使用值指针的链表(也使用堆):
struct节点2{
结构值*valuePtr;
节点*下一步;
}
sizeof(struct Node2)==8(指针也是4个字节),但随后为位于别处的“Value”实例添加另外4个字节:
struct Node2*head=calloc(sizeof(struct Node2),1);//calloc零内存
head->valuePtr=calloc(sizeof(结构值),1);
结构节点2*当前=头部;
对于(大小i=0;i<10;i++){
当前->下一步=calloc(sizeof(struct Node2),1);
当前->值ptr=calloc(sizeof(struct Value),1);
当前=当前->下一步;
}
这个版本现在将消耗
10*(8+4)==120
字节,但是随着分配的增加,碎片化的可能性也会增加

总之:
  • 值数组:
    n*sizeof(元素)
  • 指向值的指针数组:
    n*(sizeof(Element*)+sizeof(Element))
  • 值的链接列表:
    n*(sizeof(元素)+sizeof(节点*)
  • 指向值的指针的链接列表:
    n*(sizeof(Element*)+sizeof(Element)+sizeof(Node*))
注意事项:
  • 这取决于语言。如果它是一种C语言或C++语言,它可以完全控制内存,那么你可以使用以上任何方法。
  • 如果是Java,那么只有原语类型(
    int
    double
    ,但不是
    string
    )是值类型,所有其他类型都是“引用类型”,并在内部使用指针,但因为它是GC环境,所以不会出现致命的内存碎片。。。希望如此
  • 如果是C#或Swift,其中可以有值类型(
    struct
    vs
    class
    ),则可以使用所有4个选项,但指针本身不会公开
  • JavaScript将内部表示抽象出来——因此您认为是一个简单的
    Number
    值数组,在内部可以是一个哈希映射或一个向量(尽管其行为相同)

这取决于您的语言-最纯形式的数组不需要使用内存来存储索引(即使使用混合数组,索引也可以抽象出来)-如果您知道每个元素需要多少内存,只需计算
n*element\u size
,就可以轻松计算出在索引
n
中提取元素的内存位置。这取决于您的语言-最纯形式的数组不需要使用内存来存储索引(即使使用混合数组,索引也可以抽象出来)-如果知道每个元素占用多少内存,就可以轻松计算在索引struct Value { int x; } sizeof(Value) == 4 bytes (assuming zero overhead) struct Value staticArray[10]; // will consume 10 * 4 == 40 bytes
struct Value* staticArrayOfPointers[10];
for( size_t i = 0; i < sizeof(staticArrayOfPointers); i++ ) {
    staticArrayOfPointers[i] = calloc( sizeof(struct Value), 1 );
}
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;
}
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;
}