在学习数据结构的链表时,你是否有以下疑惑
- LinkList *L,和LinkList L有什么区别?
- 到底是用" . "去访问结构体内部元素还是使用"->"去访问?
下面我将一一解答你的疑问:
以下面代码为例讲解
typedef struct Node {
int data;
struct Node* next;
} *LinkList, Node;
1.LinkList *L1,和LinkList L2的区别
(为了区分,我定义为L1和L2)
LinkList *L1:这里的L1是指向LinkList指针的指针,即,L1 存储的是一个指向 LinkList
类型的指针的地址。
LinkList L2:这里的L2是LinkList指针的别名,即,L2存储一个指向 LinkList
类型的指针(即 Node
结构体指针)。
2.什么时候使用箭头运算符->
- 因为L1是指向LinkList指针的指针,所以需要解引用解引用一次可以得到
LinkList
(即Node
结构体指针),所以使用时要使用*L;此时的*L就相当于是L2了。然后使用箭头运算符"->"访问成员。像这样:(*L1)-L>data;(注意:这里(*L)需要加括号,因为->的优先级要比*高)// 定义 LinkList *L1,即指向指向头节点的指针的指针 LinkList *L1;
L2
是一个指向LinkList
类型的指针的别名,也就是Node
结构体指针。可以直接使用箭头运算符->
访问成员。L2->data;// 定义 LinkList L2,即指向头节点的指针 LinkList L2;
以上的*L1相等于L2的地位。都是指向指向 Node
结构体的指针。
3.什么时候能用 “.”访问
当L1和L2为节点本身时就可用 “.”访问了。
由以上的讲解你应该清楚,*L1和L2都是指向节点的指针,所以,再解引用一次就得到了节点本身,即real Node。具体写法如下:
(**L1).data;
(*L2).data;
完整代码例子如下:
// 创建链表的函数
void CreateList(LinkList *L, int n) {
LinkList p;
// 分配头节点内存并初始化
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
// 循环创建链表
for (int i = 0; i < n; i++) {
// 分配节点内存
p = (LinkList)malloc(sizeof(Node));
// 初始化节点数据
p->data = i + 1;
// 将节点插入链表头部
p->next = (*L)->next;
(*L)->next = p;
}
}
// 打印链表的函数
void PrintList(LinkList L) {
LinkList p = L->next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}