![](https://i-blog.csdnimg.cn/blog_migrate/71c593d5af79bde482a61ae72b450a79.png)
单链表的基本单位
val存储值,next指向下一个结构体的地址
struct ListNode
{
int val;
struct LisNode*next;
}
单链表的增删查改功能实现
链表打印
void PrintSLT(SLTNode*phead)
{
SLTNode* cur = phead;//把首指针存入
while (cur!=NULL)
{
printf("%d->", cur->data);
cur = cur->next;//cur始终作为结构体地址
}
printf("NULL");
printf("\n");
}
尾增
void PushbackSLT(SLTNode**pphead,SLTD new_data)
{
SLTNode* phead = * pphead;
//创建一个结构体变量返回它的指针
//新结构体变量的data改为插入的数据并把next置空
SLTNode* new_next = (SLTNode*)malloc(sizeof(SLTNode));
if (new_next == NULL)
{
return;
}
new_next->data = new_data;
new_next->next = NULL;
//指针为空时,phead的值改为new_next,所以要传入二级指针
if (phead == NULL)
{
*pphead = new_next;
return;
}
//指针不为空
SLTNode* tail = phead;
//找到最后一个结构体的指针
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = new_next;//最后一个结构体的指针位值更新为新指针位置
}
头增
void PushfrontSLT(SLTNode** pphead, SLTD new_data)
{
SLTNode* cur = *pphead;
SLTNode* new_next = (SLTNode*)malloc(sizeof(SLTNode));
if (new_next == NULL)
{
return;
}
new_next->data = new_data;
new_next->next = cur;
*pphead = new_next;
}
尾删
void PopbackSLT(SLTNode** pphead)
{
SLTNode* phead = *pphead;
SLTNode* cur = phead;
//没有结构体,不能删
if (phead == NULL)
{
return;
}
//只有一个结构体,phead变成NULL,释放空间
else if(phead->next==NULL)
{
free(phead);
*pphead = NULL;
}
//有两个结构体
//找到尾部的前一个
else {
while (cur->next->next != NULL)
{
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
}
头增
//头删
void PopfrontSLT(SLTNode** pphead)
{
SLTNode* phead = *pphead;
//没有结构体
if (phead == NULL)
{
return;
}
//只有一个时
else if (phead->next == NULL)
{
free(phead);
*pphead = NULL;
}
else {
//大于一个时
*pphead = phead->next;
free(phead);
}
}
单链表和顺序表的区别
顺序表物理地址连续的,单链表只是逻辑上连续实际上物理地址并不一定连续。顺序表如果头插或者中间插的话往往要进行数据覆盖,从而提高时间复杂度,而单链表只需要改变前驱节点就行。
单链表的节点可以为空,表示空链表。而顺序表结构体指针,不能为空。结构体指针为空表示没有开辟空间了。因此对顺序表结构体指针要断言,而单链表不用。但单链表二级指针要断言,理由同上。
单链表的特点
单向性,无法访问前面节点的值。比如要删除重复的值时,无法确定是否重复出现。
头节点无前驱节点,后节点后驱节点,造成要特殊讨论。如上面的头插。
解决这些问题: