算法题的对数据结构相关知识的要求较高,接下来将学习一段时间的数据结构,今天来介绍一下C语言中的指针、结构体和链表的知识。
指针
定义
指针是C语言中一个非常重要的知识点。首先需要明确的一点是:指针本身是一种数据类型,该变量保存的是对应类型变量的一个地址。保存了这个地址后,我们就可以通过这个地址访问到变量,操作该变量所在的内存空间(可以修改该变量)。
形象解释
小明在A地点放了1kg黄金 ,小明将A地址的地址写在一张纸Z1上,这张纸就相当于是一个指针变量指向黄金。小明将这张纸放在了B地点 ,又写了一张纸Z2,将Z1这张纸存放的地址 B地点 写在Z2这张纸上,那么Z2就相当于一个指针变量指向Z1。这样下来,小明就可以通过Z1找到黄金,也可以通过Z2找到Z1,从而找到黄金。这种方式就是通过指针访问变量的形象解释。
定义格式
数据类型 *指针变量名= 某个变量的地址/一段内存的地址;
同时,指针可以是多层的,例如要保存一个单层指针的地址,则可以加多一个*,然后对要保存的单层指针取址。(以此类推)
示例代码
cs
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 10;
//定义一个指针变量存储变量a的地址
int *z1 = &a;
//直接打印z1
printf("z1=%d\n", z1);
//打印z1地址下对应的变量
printf("*z1=%d\n", *z1);
//改变z1保存的地址对应的数据
*z1 = *z1 + 10;
printf("*z1=%d\n", *z1);
int **z2 = &z1;
printf("*z2=%d\n", *z2);
printf("**z2=%d\n", **z2);
}

结构体
定义
结构体是C语言中一种重要的用户自定义复合数据类型,它允许将多个不同类型的数据元素(称为成员)组织在一起,形成一个整体。结构体的主要作用是封装数据,便于管理和操作复杂的数据集合。其作用和地位相当于Java中的对象,可以通过名字调用里面的成员并进行操作。
定义格式
①使用结构体变量
创建:struct 结构体名{ }; 大括号中可以书写不同类型的数据(属性)
调用:struct 结构体名 调用时的名 ; 相当于Java中的创建类的对象,然后通过对象调用属性
注意:使用结构体变量是调用使用的符号是" . "!
示例代码
cs
#include <stdio.h>
#include <stdlib.h>
struct Student {
int id;
int age;
char name;
};
int main() {
struct Student s;
s.name = 'M';
s.age = 18;
s.id = 27;
printf("name=%c\n", s.name);
printf("age=%d\n", s.age);
printf("id=%d\n", s.id);
return 0;
}

②使用结构体指针
创建:struct 结构体名{ };
调用:struct 结构体名 *调用时使用的名=(结构体名 *)malloc(sizeof(结构体名))
注意:使用结构体指针需要使用malloc函数分配内存地址,并且需要用小括号转换成"结构体类型的指针"的数据类型。并且,与使用结构体变量不同的还有在调用的时候需要用符号 "->" 调用结构体中的属性。
示例代码
cs
#include <stdio.h>
#include <stdlib.h>
struct Student {
int id;
int age;
char name;
};
int main() {
struct Student *s = (Student *)malloc(sizeof(Student));
s->age = 18;
s->id = 27;
s->name = 'm';
printf("age=%d\n", s->age);
printf("id=%d\n", s->id);
printf("name=%c\n", s->name);
return 0;
}
输出结果与上面"使用结构体变量"一致!
链表
定义
链表是通过指针相连保存数据的一种数据结构,其存储单元为节点。链表的特点是节点在内存中不必连续存储,节点的逻辑顺序是通过每个节点中的指针链接实现的,可以只通过头节点访问到链表不同位置的数据。
一个节点需要包括两个变量:一个用来存储数据,另一个变量是一个指针变量,用来存储下一个节点的地址。由于两个变量类型不一致,就需要用到结构体指针。
定义方法(先介绍不用循环的)
我们要书写一个结构体指针,在里面定义两个变量data和*next,然后在主函数中创建多个节点,并分配内存,最后通过调用data和*next并对其赋值,就可以建立起各个节点的联系。注意,创建完链表之后只需要使用头节点操作链表中的数据!
如果想要在链表中添加数据,只需要创建一个新的节点,赋上对应的data和*next即可。以添加到链表最后为例,data可以是键盘输入的,*next为NULL。
示例代码
cs
#include <stdio.h>
#include <stdlib.h>
//定义一个结构体
struct ListNode {
int data;
ListNode *next;
};
int main() {
//先创建多个节点,并分配内存
ListNode *node1 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node2 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node3 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node4 = (ListNode *)malloc(sizeof(ListNode));
ListNode *node5 = (ListNode *)malloc(sizeof(ListNode));
node1->data = 100;
node2->data = 200;
node3->data = 300;
node4->data = 400;
node5->data = 500;
//接下来将所有的节点连接
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = node5;
//接下来只能借助头节点进行链表的相关操作
printf("1:%d\n", node1->data);
printf("2:%d\n", node1->next->data);
printf("3:%d\n", node1->next->next->data);
printf("4:%d\n", node1->next->next->next->data);
printf("5:%d\n", node1->next->next->next->next->data);
//添加一个新的节点
ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
node5->next = newNode;
//将输入的数字添加到下一个节点上
int n;
printf("请输入一个数据添加到下一个节点:");
scanf("%d", &n);
newNode->data = n;
newNode->next = NULL;
printf("6:%d\n", node1->next->next->next->next->next->data);
return 0;
}
