链表算是我们学习数据结构的过程中遇到的第一个拦路虎了,今天我们就来一举拿下链表。
要学习链表首先我们需要创建一个链表,我们链表里面是要存储一种数据,我们假定我们存储 int 类型的数据,那我们先重定义一下 int 。
typedef int SLTDataType;
链表嘛,我们肯定是要把各个数据给链接起来的,那我们就要先创建一个链表的节点类型,
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
我们创建的结构体中包含两个变量,一个存我们的数据,另一个存我们下一个节点的地址方便我们访问。
接下来就是我们接口的书写了,我们首先应该写一个创建节点的接口
SListNode* BuySListNode(SLTDateType x);
SListNode* BuySListNode(SLTDateType x)
{
SListNode* p = malloc(sizeof(SListNode));
if(!P)
{
perror("malloc");
exit(-1);
}
p->data = x;
p->next = NULL;
return p;
}
为了方便我们后续接口的书写,我们可以先书写一个 insert 接口,方便我们待会写头插尾插接口
void SListInsertAfter(SListNode* pos, SLTDateType x);
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
SListNode* p = BuySListNode(x);
p->next = pos->next;
pos->next=p;
}
数据结构无外乎增删查改,接下来我们就开始接口的书写。
一、增
我们这里分为头插和尾插。
1、头插
头插的话就是在最前面插入一个节点。
void SListPushFront(SListNode** pplist, SLTDateType x);
void SListPushFront(SListNode** pplist, SLTDateType x)
{
SLIstNode* p = BuySListNode(x);
p->next = *pplist;
*pplist = p;
}
2、尾插
尾插的话比较麻烦,因为我们没办法直接找到尾节点,所以我们要遍历这个链表,直到找到一个节点的 next 是 NULL,然后再进行插入。
void SListPushBack(SListNode** pplist, SLTDateType x);
void SListPushBack(SListNode** pplist, SLTDateType x)
{
if(*pplist)
{
SListNode* p = BuySListNode(x);
*pplist = p;
}
else
{
SListNode* p =*pplist;
while(p->next)
{
p = p->next;
}
SListInsertAfter(p,x);
}
}
二、删
删除也是有头删和尾删的区分的。
1、头删
void SListPopFront(SListNode** pplist);
void SListPopFront(SListNode** pplist)
{
assert(*pplist);
*pplist = *pplist->next;
}
2、尾删
尾删和尾插一样的问题,尾部节点没有现成的,需要我们来遍历我们的链表
void SListPopBack(SListNode** pplist);
void SListPopBack(SListNode** pplist)
{
assert(*pplist);
if(*pplist->next)
*pplist = NULL;
else
{
SListNode* p = *pplist;
while(p->next->next)
{
p = p->next;
}
free(p->next);
p->next = NULL;
}
}
三、查
查找的话我们就遍历我们的链表,当遇到存放我们想要的数据的节点时候把这个节点的地址作为返回值返回就好了
SListNode* SListFind(SListNode* plist, SLTDateType x);
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
while(plist->next)
{
if(plist->data == x)
return plist;
plist = plist->next;
}
return NULL;
}
四、改
要修改一个节点,我们要传入这个节点的地址,然后把其中的data数据修改就好了,一般情况下我们是要配合查找接口使用的。
void SListRevise(SListNode* plist, SLTDateType x);
void SListRevise(SListNode* plist, SLTDateType x)
{
plist->data = x;
}