为什么在链表的C实现中需要指针?
为什么在C中链表的实现中使用指针很重要 例如:为什么在链表的C实现中需要指针?,c,pointers,linked-list,C,Pointers,Linked List,为什么在C中链表的实现中使用指针很重要 例如: typedef struct item { type data; struct item *next; } Item; typedef struct list Item *head; } List; 如果我只使用没有指针的相同实现,会发生什么情况?如果没有指针,每个
typedef struct item
{
type data;
struct item *next;
} Item;
typedef struct list
Item *head;
} List;
如果我只使用没有指针的相同实现,会发生什么情况?如果没有指针,每个列表项都包含另一个列表项(
next
),其中包含另一个列表项。它又包含另一个列表项。等等
您最终会得到一个无限大的数据结构,该结构将使用无限大的内存,而这当然无法工作。您最终会得到类似的结果
typedef struct item
{
type data;
struct item next;
} Item;
size-of-Item = size-of-type + size-of-Item
现在,C编译器将尝试计算项的大小。但是由于next
正好嵌入到项中,因此它将以这样一个等式结束
typedef struct item
{
type data;
struct item next;
} Item;
size-of-Item = size-of-type + size-of-Item
这是无限的。因此,我们有一个问题。因此,C需要指针,因此
size-of-Item = size-of-type + size-of-pointer
已经关门了。更有趣的是,即使您在Java、Python或Haskell等语言中这样做,您实际上是在隐式存储一个指针(他们称之为引用)来打破循环。它们只是对您隐藏事实。实际上,您不需要使用指针来实现公开链表接口的数据结构,但您确实需要它们来提供链表的性能特征
指针的替代品是什么?嗯,项
需要有一些方法来引用下一项。由于各种原因,它无法聚合下一项,其中一个原因是这将使结构“递归”,因此无法实现:
// does not compile -- an item has an item has an item has an item has...
typedef struct item
{
type data;
struct item next;
} Item;
您可以做的是拥有一个项目数组,并在上面实现链表:
Item *storage[100];
typedef struct item
{
type data;
int next; // points to the index inside storage of the next item
} Item;
这看起来是可行的;您可以使用一个向列表中添加项目的函数和另一个删除项目的函数:
void add_after(Item *new, Item *existing);
void remove(Item *existing);
这些函数要么从数组中删除现有的(注意更新上一项的下一个“指针”),创建一个空槽,要么找到现有的项,并将新的插入存储器的空槽中(更新下一个指向那里)
问题在于,这使得add\u after
和remove
操作无法在固定时间内实现,因为现在需要搜索数组并在空间不足时重新分配它
由于固定时间的添加/删除是人们使用链表的原因,这使得非指针方法仅在智力练习中有用。对于实际列表,使用指针意味着您可以在固定时间内执行这些操作。指针用于动态分配内存
您可以将列表实现为一个简单的数组,但这意味着您要分配一个连续的内存区域,这对于一个大的列表来说是没有效率的。此外,阵列更难扩展(如果达到其最大大小,则必须重新分配阵列)
因此,对于大型列表,动态分配是首选,对于每个元素,它可以在任何位置将其分配到内存中,连续分配或不分配,并且您可以轻松地扩展它
此外,由于结构尚未定义,且无法确定结构的大小,因此无法在struct item
中存储另一个struct item
:
这是无法做到的:
typedef struct item
{
type data;
struct item next;
} Item;
因此使用指针是因为在编译结构时可以确定指针的大小(该平台上整数的大小) c中指针的重要性
优点:-
执行速度将很高
指针允许我们访问函数外部的变量
减少代码的大小
没有指针:-
代码大小将得到增加
我们无法有效地维护数据
在列表中,指针用于指向列表中的下一项。如果未声明指针,则表示无法访问列表中的多个项
如果您在运行时动态分配一些内存,那么实际上非常需要指针
在C中创建列表不需要指针。指针列表是否可取取决于您的应用程序。在用语言实现指针概念之前,人们使用链表。对某些人来说(使用指针)有时理解起来更简单。您也不需要包含数据的结构
一个简单的数组就可以了。你需要:
- 一个整数数组,用于保存索引(类似于指针)。数组内容可以是
-1
(指针术语中的nil
或NULL
),也可以是0。。N-1
,表示:链接的下一个元素的数组索引。索引数组的索引表示数据数组中项的索引
- 一个数组,用于上面“列表”中要“连接”的任何数据
这就是你所需要的
数组而不是指针列表可能具有
- 优势,如果您的数据量没有变化(没有增长)。在这种情况下,优势是巨大的。如果您知道将遇到的最大数据量,并且可以提前分配数据,那么数组实现将比任何指针链表快得多。特别是,如果您只插入,但不需要删除
- 缺点否则。在这种情况下,缺点可能是巨大的
请仔细阅读
因此,您的示例如下所示:
type data[N]; // or: type *data = new type [N];
int links[N]; // or: int *links = new int [N];
这就是从一个简单的测试用例开始所需的全部内容。有多种“列表”。您显示的实现是一个“链表”。没有指针就没有“链接”,所以我们需要查看其他类型的列表
因此,首先,如果从结构定义中删除*
,会发生什么:它不会编译。Y
list = realloc(list, newcount * sizeof(struct item));
list[newitem] = blah;