这些代码之间有什么区别?
1)
struct MyStruct
{
int num;
} ms[2];
ms[0].num = 5;
ms[1].num = 15;
2)
struct MyStruct
{
int num;
MyStruct *next;
};
MyStruct *ms = new MyStruct;
ms->num = 5;
ms->next = new MyStruct;
ms->next->num = 15;
我可能对链接列表和列表有点困惑,特别是对某些内容有用吗?请多解释一下。
答案 0 :(得分:4)
您的第一个定义......
struct MyStruct
{
int num;
} ms[1];
...使用单个元素创建静态分配的数组。程序运行时,您无法更改数组的大小;这个数组永远不会包含多个元素。您可以通过直接索引访问数组中的项目;例如,ms[5]
会得到数组中的第六个元素(记住,C和C ++数组是0索引的,所以第一个元素是ms[0]
),假设你已经定义了一个合适的数组大小
你的第二个定义......
struct MyStruct
{
int num;
MyStruct *next;
};
...创建动态分配的链表。此列表的内存在运行时动态分配,链接列表可在程序生命周期内增长(或缩小)。与数组不同,您无法直接访问列表中的任何元素;要获得第六个元素,你必须从第一个元素开始,然后迭代5次。
答案 1 :(得分:2)
关于代码中的错误,第一个构造静态数量的MyStruct元素并将它们存储在ms数组中,因此ms是一个MyStruct结构数组,当然在这里你的意思是它只有2个元素,稍后您不能将任何其他元素添加到ms数组,虽然您限制了MyStruct元素的数量,而在第二种情况下,当您有链接列表时,您可以链接任意数量的MyStruct元素,这将导致对于动态数量的MyStruct元素,第二种情况允许您在运行时添加任意数量的MyStruct,第二种情况应该在概念上在内存中如下:
[ MyStruct#1 ] ----> [ MyStruct#2 ] ----> [ NULL ]
例如,NULL可以是MyStruct#3,而第一个是:Z
[ MyStruct#1 ] ----> [ MyStruct#2 ]
就是这样,不能添加MyStruct#3。
现在让我们来看看你写的代码:
struct MyStruct
{
int num;
} ms[1];
ms[1]
实际上意味着创建一个MyStruct元素的ms数组
接下来的代码假设您创建了两个:
ms[0].num = 5;
ms[1].num = 15
因此应该是:
struct MyStruct
{
int num;
} ms[2];
它会正常工作!并记住我为它做的简单说明:
[ MyStruct#1 ] ----> [ MyStruct#2 ]
第二种情况:
struct MyStruct
{
int num;
MyStruct *next;
};
MyStruct *ms = new MyStruct;
ms->num = 5;
ms->next = new MyStruct;
ms->next->num = 15;
如果将源代码保存为new
,则此代码将使用C ++运算符.cpp
,您将能够编译为无错误的C ++应用程序,而对于C,语法应该如此更改:
struct MyStruct
{
int num;
MyStruct *next;
};
MyStruct *ms = (MyStruct *) malloc(sizeof MyStruct);
ms->num = 5;
ms->next = (MyStruct *) malloc(sizeof MyStruct);
ms->next->num = 15;
并且不要忘记为#include <stdlib.h>
功能添加malloc()
,您可以阅读有关此功能的更多信息here。
第一种情况回顾了我对链表的说明:
[ MyStruct#1 ] ----> [ MyStruct#2 ] ----> [ NULL ]
其中NULL实际上是ms-&gt;下一个MyStruct结构的下一个元素,为了解释它更多回忆ms-&gt; next是MyStruct的指针,我们在堆中分配了一个空间,所以它现在指向一个块记录相同大小的MyStruct结构。
最后,这是一个关于何时使用链接列表以及何时使用数组的 Stackoverflow 问题,这样您就可以确切地了解为什么全世界的人们有时更喜欢链接列表和数组其他次。
答案 2 :(得分:1)
哦,我的朋友,有几十种不同类型的数据结构,几乎只包含一堆num
值或其他任何值。程序员不仅仅使用数组的原因是所需内存量的差异,以及执行哪些操作对于您的特定需求最为重要的便利性。
链接列表恰好可以非常快速地添加或删除单个项目。权衡的是找到列表中间的项目相对较慢,以及next
指针所需的额外内存。一个大小合适的数组在内存中非常紧凑,您可以非常快速地访问中间的项目,但是要在最后添加一个新项目,您必须事先知道元素的最大数量,这通常是不可能的或浪费内存,或重新分配一个更大的数组并复制一切,这很慢。
因此,有些人不知道他们的列表需要多大,而且大多数人只需要处理列表开头或结尾的项目,或者总是遍历整个列表,并且更关心执行速度比保存几个字节的内存,很可能选择一个数组的链表。
答案 3 :(得分:1)
列表和数组之间的主要区别通常是:
在列表中排序显式;每个元素存储前一个/后一个元素的位置。在数组中排序是隐式;假设每个元素具有前/后元素。请注意,单个列表可能包含多个排序。例如,您可以使用
struct dualList {
T data1;
K data2;
struct dualList *nextT;
struct dualList *nextK;
};
之类的内容
这允许您以两种不同的方式订购相同的列表,一种是data1
,另一种是data2
。
相邻的数组元素位于相邻的内存位置;相邻列表元素不必位于相邻位置。
Arrays提供对其元素的随机访问;列表仅提供顺序访问(即,您必须沿着列表向下查找元素)。
数组(通常)固定长度 1 - 向数组中添加元素或从数组中删除元素不会更改数组的大小。列表可以根据需要增长或缩小。
列表非常适合维护动态变化的值序列,尤其是在值需要保持有序的情况下。它们不是那么热,用于存储需要快速且经常检索的相对静态数据,因为您无法随机访问元素。
realloc
来调整内存块的大小,但是需要仔细完成并且可能有点像PITA。 答案 4 :(得分:0)
当元素排序很重要时,链接列表很有用,并且事先不知道元素的数量。此外,访问链表中的元素需要O(n)时间。当您在列表中查找元素时,在最坏的情况下,您将必须查看列表中的每个元素。
对于数组,必须事先知道该数字。在C中定义数组时,必须将其大小传递给它。另一方面,访问数组元素需要O(1)时间,因为元素可以通过索引来寻址。使用链表,这是不可能的。
然而,这不是与C ++相关的问题,因为链表和数组的概念与C ++无关。
答案 5 :(得分:0)
数组是连续的预分配内存块,而链表是运行时分配的(malloc
)内存块(不一定是连续的)的集合,它们通过指针相互链接({{1} })。如果您在编译时知道需要存储的最大元素数,通常会使用*next
数组。但是,如果您不知道需要存储的元素的最大数量,则structs
的链接列表非常有用。此外,使用链接列表,元素的数量可能会更改,添加和删除元素。