目录
一、单链表的特点
数据空间是不连续的,相较于顺序表其数据的存储和删除在相应情况下效率更高。
二、链表实现思想
利用结构体定义一个数据节点 :包含 数据 和 指向下一个数据节点的指针
这样就可以通过调用 一个数据节点 找到 n 个数据节点 ,进而形成 表状 的数据储存形式 。
相应图解:
三、具体实现
1. 定义数据节点
typedef int Slist_type //重命名数据类型 ,方便后期的应用和修改
typedef struct Slist_code
{
struct Slist_type date; //用来存储数据
struct Slist_code* next; //指向下一个数据的指针
}Slist_code;
2. 进行数据的头插
先定义一个创建新空间的函数(方便后面的重复使用)
Slist_code* Slist_ADD()
{
Slist_code* Newcode = (Slist_code*)malloc(sizeof(Slist_code));
assert(Newcode);
Newcode -> next = NULL;
Newcode -> date = 0;
return Newcode;
}
注:因为每次头插链表的起始点需要更改,所以:
函数参数要设定传入二级指针,因为要修改指针 。
(链表起点是一个指针,指向起始节点 ,未设置起始节点时,默认为初始化为NULL)
void Head_ADD_code(Slist_code**p,Slist_type date)
{
assert(p);
Slist_code* tem = Slist_ADD_code(date);
tem->next = *p; //新节点存放旧节点位置
*p = tem; //起始位置要变成新节点的位置
}
3. 任意位置插入数据
这里插入的步骤的原理通俗点讲就是 : 新节点将上一节点干的活揽过来(新节点 存放插入位置前一个节点 存放的指针),并且 上一个节点存放的指针 要改为 指向新节点 。
(要注意到这里设置的是在寻找的对应位置后插入一个数据,如果没找到就在最后插入一个数据)
注:因为,要考虑到没有数据的情况 :再添加完第一个数据后要修改链表起点,指向首次开辟的 内存空间 。
void Arb_ADD_code(Slist_code** p ,Slist_type date)
{
assert(p); //检查防止传入空二级指针
if (*p)
{
Slist_code* tem = *p;
Slist_code* tem2 = *p;
for (; tem->next != NULL;)
{
if (tem->date == date) //如果找到对应位置,弹出
{
break; //此时 tem 记录的是对应的数据节点
}
tem = tem->next; //没找到就 遍历到下一个节点
}
Slist_code* tem1 = Slist_ADD_code(date); //tem记录的(寻找到的对应位置)或
tem1->next = tem->next; (最后的节点)
tem->next = tem1;
}
else //如果没有数据
{
*p = Slist_ADD_code(date);
}
}
4. 任意数据的删除
删除就是将删除位置的前后两个节点重新相连 ,后节点的位置从 要删除的节点中 找到 ,
并且,每次遍历循环时要用一个临时变量把前一个节点记住 ,这样就能既找到后节点,又找到前节点 。
注 :特殊情况 1 . 删除起点时,起点也要随之改变
2 . 未找到要删除的数据
3 . 空间无数据
void Slist_Delet(Slist_code**p,Slist_type date)
{
assert(p);
Slist_code* tem = *p;
Slist_code* tem1 = *p;
assert(*p); //防止无数据
int k = 0;
for (;tem->next != NULL; tem = tem->next)
{
if (tem->date == date) //查找元素
{
k = 1;
break;
}
tem1 = tem; //始终记录 tem 前的一个节点
}
if (k||tem->date == date) //如果全不相等
{
Slist_code* tem2 = (*p)->next; //先把首数据的下一个节点地址存储
if ((*p)->date == date) //如果首数据被删除
{
free(*p);
*p = tem2; //起点要改为 tem2
}
else
{
tem1->next = tem->next;
free(tem);
}
}
else
printf("没找到\n");
}
5,对链表的打印
打印不需要修改指针,参数传一级指针就行。
void Print_date(Slist_code* P)
{
for(;P;P = P->next)
{
printf("%d\n",P->date);
}
printf("\n");
}