以下是语法,是C编程语言中链表的一部分
struct tag-name
{
type member1;
type member2;
.......
.......
struct tag-name *next;
};
为什么我们必须在下一个指针变量之前再次写struct标记名。为什么我们不能使用void * next或int * next或类似的东西?
答案 0 :(得分:0)
对于链接列表,next
条目(或其名称)必须指向下一个节点。在您的情况下,节点类型为tag-name
。
因此您需要<type> next;
是您寻求指向名为x的结构的指针的方式,即struct x *
。因此,您看到的代码使您感到困惑/不安。你能简化一下吗?是的你可以。 C有typedef
。你可以做
typedef struct tag-name node;
现在您可以拥有
struct tag-name
{
type member1;
type member2;
.......
.......
node *next;
};
您问,我可以拿void* next
吗?是的,但是为什么呢?您将不得不继续将该指针转换为指向该结构的指针(编译器并不隐式知道其指向的内容),而且代码阅读器也会感到惊讶,因为他们希望下一个指针成为指向节点的指针。
您问是否可以是int next
。不,它不能,下一个对象是节点,而不是int
答案 1 :(得分:0)
考虑链接列表的典型插图:
node node node
+------+------+ +------+------+ +------+------+
| data | next | --> | data | next | --> | data | next | --> ...
+------+------+ +------+------+ +------+------+
列表中的每个项目都是某个类型的 node ,并且该节点包含一个next
成员,该成员明确指向列表中的下一个 node 。在C语言中,通常会转换为struct
类型,例如
struct node
{
T data; // for some type T
struct node *next;
};
IOW,每个struct node
都有一个next
成员,该成员指向另一个struct node
类型的对象-不是int
,不是void
等,这这就是为什么我们不将next
声明为int *
或void *
或其他原因的原因。
但是...
根据实现列表的方式,您可以 使用struct node *
以外的其他内容作为next
项目。通常,当我们实现列表时,我们会根据需要使用malloc
动态分配每个节点。但是,如果您知道列表的大小永远不会超过某个已知的,较小的值,则可以将struct node
的 array 保留为“堆”,而将{{1 }}成员可以是数组索引值:
next
然后初始化您的“堆”,以便每个元素明确指向数组中的下一个:
struct node
{
T data;
int next; // holds the *index* of the next element
} heap[SOME_SIZE];
现在,您只需要几个整数,一个指向数组中的第一个可用元素,另一个指向列表的开头:
for ( int i = 0; i < SOME_SIZE-1; i++ )
{
heap[i].next = i+1;
}
heap[SOME_SIZE-1].next = -1; // use -1 to indicate "null"
“分配”一个节点就成了在“堆”中找到第一个空闲节点的问题:
int avail = 0; // initially points to the first element in the "heap"
int head = -1; // initially "null"
“释放”节点仅意味着将索引添加回int node = avail; // get the index of the next available node in the "heap";
avail = heap[avail].next; // update avail to point to the next available node
列表的开头:
avail
请记住,heap[node].next = avail; // set this node point to the first free element
avail = node; // make this node the first free element;
和node
不是节点对象,它们只是索引到节点对象的数组中。
我们通常不这样做,因为从概念上讲,avail
可以直接指向另一个next
对象,而不是指向数组的索引。我们仍然可以使用固定大小的数组作为“堆”,我们只使用每个元素的地址而不是其索引。