Arrays 内存空间使用:链表指针与数组索引
我正在学习链表,很好奇链表与具有相同元素的数组相比需要多少内存空间。列出了以下链接列表的缺点: 列表中的每个元素都需要为指针提供额外的内存空间 但是数组也必须为每个元素的索引使用内存,对吗 我猜索引比指针占用的内存要少,但我很好奇我们将讨论什么样的比率。有什么想法吗 如果使用值类型作为数组元素,那么数组使用的存储空间会更少 我将以C为例: 1.值数组: 2.如果是指针数组,则: 链表现在在内存中至少有Arrays 内存空间使用:链表指针与数组索引,arrays,pointers,indexing,data-structures,linked-list,Arrays,Pointers,Indexing,Data Structures,Linked List,我正在学习链表,很好奇链表与具有相同元素的数组相比需要多少内存空间。列出了以下链接列表的缺点: 列表中的每个元素都需要为指针提供额外的内存空间 但是数组也必须为每个元素的索引使用内存,对吗 我猜索引比指针占用的内存要少,但我很好奇我们将讨论什么样的比率。有什么想法吗 如果使用值类型作为数组元素,那么数组使用的存储空间会更少 我将以C为例: 1.值数组: 2.如果是指针数组,则: 链表现在在内存中至少有10*8(80)个字节,并且也可能是碎片,因为每个节点可能存在于内存中的不同位置 4.如果是使用
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
)是值类型,所有其他类型都是“引用类型”,并在内部使用指针,但因为它是GC环境,所以不会出现致命的内存碎片。。。希望如此string
- 如果是C#或Swift,其中可以有值类型(
vsstruct
),则可以使用所有4个选项,但指针本身不会公开class
- JavaScript将内部表示抽象出来——因此您认为是一个简单的
值数组,在内部可以是一个哈希映射或一个向量(尽管其行为相同)Number
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
)是值类型,所有其他类型都是“引用类型”,并在内部使用指针,但因为它是GC环境,所以不会出现致命的内存碎片。。。希望如此string
- 如果是C#或Swift,其中可以有值类型(
vsstruct
),则可以使用所有4个选项,但指针本身不会公开class
- 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;
}