前言
之前大摆了5天多,没怎么学编程,自昨日起,觉不可如此,痛定思痛,开始继续学习,昨天刷了20多道简单级别的力扣,今天想把链表好好巩固一下,于是乎,把单链表的增删查改搞了出来,还用单链表写了通讯录,等下写完博客在去和双链表缠斗一番,ok,王子公主请看下文
在大刀阔斧地写代码前,我们先稍稍复习一下书面知识。
1. 链表的概念及结构
概念:
链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。
为什么还需要指针变量来保存下⼀个节点的位置?
struct SListNode{int data; // 节点数据struct SListNode * next ; // 指针变量⽤保存下⼀个节点的地址};
- 1、链式机构在逻辑上是连续的,在物理结构上不⼀定连续
- 2、节点⼀般是从堆上申请的
- 3、从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续
2.链表的分类
3.单链表的增删查改
毕竟只是增删查改,我们只需要写两个文件就够了,一个头文件,一个源文件写函数,
typedef int SLTDataType; typedef struct SListNode { // }SLTNode;void SLTPrint(SLTNode* phead);//头部插入删除/尾部插入删除 void SLTPushBack(SLTNode** pphead, SLTDataType x); void SLTPushFront(SLTNode** pphead, SLTDataType x); void SLTPopBack(SLTNode** pphead); void SLTPopFront(SLTNode** pphead);//查找 SLTNode* SLTFind(SLTNode* phead, SLTDataType x); //在指定位置之前插入数据 void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x); //删除pos节点 void SLTErase(SLTNode** pphead, SLTNode* pos); //在指定位置之后插入数据 void SLTInsertAfter(SLTNode* pos, SLTDataType x); //删除pos之后的节点 void SLTEraseAfter(SLTNode* pos); //销毁链表 void SListDesTroy(SLTNode** pphead);
接着开始实现函数
#include"SLT.h"
SLTNode* creat(SLTDataType x)
{
SLTNode* p = malloc(sizeof(SLTNode));
p->val = x;
p->next = NULL;
return p;
}
void SLTPrint(SLTNode* phead)
{
while (phead)
{
printf("%d ", phead->val);
phead = phead->next;
}
puts("");
}
//尾部插入
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
if (*pphead == NULL)
*pphead = creat(x);
else
{
while ((*pphead)->next)
{
*pphead = (*pphead)->next;
}
(*pphead)->next = creat(x);
}
}
//头部插入
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
if (*pphead == NULL)
if (*pphead == NULL)
*pphead = creat(x);
else
{
SLTNode* new = (*pphead);
*pphead = creat(x);
(*pphead)->next = new;
}
}
//尾部删除
void SLTPopBack(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);
if (((*pphead)->next) == NULL)
*pphead= NULL;
else
{
while ((*pphead)->next->next)
{
(*pphead) = (*pphead)->next;
}
free((*pphead)->next);
(*pphead)->next = NULL;
}
}
//头部删除
void SLTPopFront(SLTNode** pphead)
{
assert(pphead);
assert(*pphead);
SLTNode* new = (*pphead)->next;
free(*pphead);
*pphead = new;
}
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
while (phead&&phead->val != x)
phead = phead->next;
if (phead == NULL)
{
printf("你要找的内容不存在\n");
return 0;
}
return phead;
}
//在指定位置之前插入数据
void SLTInsertFront(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pphead);
assert(*pphead);
assert(pos);
if ((*pphead) == pos)
{
*pphead = creat(x);
(*pphead)->next = pos;
}
else
{
while ((*pphead)->next != pos)
{
*pphead = (*pphead)->next;
}
SLTNode* new = (*pphead)->next;//不对劲!!!!!!
(*pphead)->next = creat(x);
(*pphead)->next->next = pos;
}
}
//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead);
assert(*pphead);
if (*pphead == pos)
{
free(pos);
*pphead = NULL;
}
else
{
while ((*pphead)->next != pos)
*pphead = (*pphead)->next;
(*pphead)->next = (*pphead)->next->next;
free(pos);
pos = NULL;
}
}
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* new = pos->next;
pos->next = creat(x);
pos->next->next = new;
}
//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{
assert(pos);
SLTNode* new = pos->next;
pos->next = pos->next->next;
free(new);
}
//销毁链表
void SListDesTroy(SLTNode** pphead)
{
assert(pphead);
while (*pphead != NULL)
{
SLTNode* p = (*pphead)->next;
free(*pphead);
*pphead = p;
}
}
ok,那么下次单链表的分享就先告一段落了,感谢观看