一、什么是单链表
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
逻辑结构:线性结构 一对一
存储结构:链式存储 内存中不一定是连续的
算法:增删改查、链表排序、链表翻转
顺序表在实际开发中无法满足大型数据量的项目,前辈们想出一种解决但数据量的数据操作方法 --> 链表
顺序表在内存中开辟空间是连续的,实际开发中这是一种奢望。 链表可以解决无法开辟连续空间的问题。
二、创建单链表
链表分为有头链表和无头链表 有头链表现在常用,相较于无头链表浪费了一个节点空间,但是会带来操作上的方便。
有头链表的创建本质就是创建头结点,我们依然是将链表在堆区创建,头结点数据域不使用,主要使用指针域。
代码实现:
link_list_t *create_linklist(void)
{
link_list_t *L=NULL;
//申请链表头结点空间
L = (link_list_t *)malloc(sizeof(link_list_t));
if(NULL==L){
puts("创建链表失败");
return NULL;
}
//初始化链表头结点
L->data = -1;//头结点数据域不适用 可以给任意值
L->next = NULL;//链表头节点指针域 置NULL 是方便操作单链表
//返回链表头结点首地址
return L;
}
三、头部插入
当链表创建完成后(本质就是创建了一个头结点),我们可以考虑使用链表对数据进行管理 首先我们研究链表的头部插入数据操作。
int head_insert(link_list_t *L,data_t value)
{
//健壮性判断
if(NULL==L){
puts("传入表参数非法\n");
return -1;
}
//创建新节点
link_list_t *N = (link_list_t*)malloc(sizeof(link_list_t));
if(NULL==N){
puts("创建新节点失败");
return -1;
}
//初始化新节点
N->data = value;
N->next = NULL;
//头部插入操作
link_list_t *q = L;
N->next = q->next;先将头结点的指针域赋值给新节点的指针域,将新节点指针域指向链表第一个
数据元素
q->next = N;
return 0;
}
四、链表遍历
插入数据后,接下来分析如何遍历链表。
int show_linklist(link_list_t *L)
{
//健壮性判断
if(NULL==L){
puts("传入表参数非法");
return -1;
}
if(NULL==L->next){
puts("表为空表 无数据可遍历");
return -1;
}
link_list_t *q = L->next;//定义一个数据节点指针变量 q
//直接指向 有效数据节点
while(NULL!=q){
printf("%d ",q->data);//打印有效数据节点的数据
q = q->next;//移动指针
}
puts("");
return 0;
}