目录
(一)单链表的结构定义及初始化
(二)单链表的尾插,头插
(三)单链表的尾删,头删
(四)单链表的查找,删除,销毁
单链表是数据结构课程里的第二个数据结构。单链表在逻辑结构是连续的,在物理结构不一定连续。因为在单链表的每一个结点的内存是在堆区动态开辟的,由操作系统来决定是否连续开辟在相同的区域。
(一)单链表的结构定义及初始化
#define SLDataType int
//单链表的结构定义
typedef struct SingleList
{
SLDataType val;
struct SingleList* next;
}SL;
单链表的每一个节点都有其数值域和指针域。数值域是当前结点所存储的数值,指针域是存储指向下一个结点的指针。这里我们定义一个宏,把SLDataType 替换成int,以后想换存储的数据类型就方便多了。我们再把单链表的数据类型struct SingleList重命名为SL。
//单链表的初始化
void InitSingleList(SL* phead)
{
assert(phead);
phead->val = 0;
phead->next = NULL;
}
(二)单链表的尾插,头插
单链表的尾插是指在单链表的结尾插进去一个新结点。我们可以创建一个函数专门封装创建一个新结点的过程
//创建一个新结点
SL* BuyNewNode(SLDataType x)
{
SL* NewNode = (SL*)malloc(sizeof(SL));
if (NewNode == NULL)
{
perror("malloc fail!\n");
eixt(1);
}
//走到这说明新结点的内存创建成功
NewNode->val = x;
NewNode->next = NULL;
return NewNode;
}
每次创建结点的时候必须要检查结点是否创建失败,而且要记得要释放空间。我们这里通过malloc申请了一片SL大小的空间。并将申请的空间解释为SL*类型,把SL里面的值赋值为x,下一个结点指向为NULL指针。
//单链表的尾插
void SingleListPushBack(SL** pphead, SLDataType x)
{
//这里需要用二级指针,因为可能传进来的指针没有结点,尾插变成头插,需要对头结点的地址进行赋值。
assert(pphead);
SL* phead = *pphead;
if (phead == NULL)
{
//说明单链表没有一个结点,需要修改头结点的地址
phead = BuyNewNode(x);
}
else
{
//需要遍历链表找到尾结点
SL* pcur = phead;
while (pcur)
{
pcur = pcur->next;
}
//我们要让链表后面的顺序为 pcur -> NewNode
pcur->next = BuyNewNode(x);
}
}
//单链表的头插
void SingleListPushFront(SL** pphead, SLDataType x)
{
assert(pphead);
//同样的头插就更需要传二级指针了
SL* phead = *pphead;
//NewNode -> phead;
SL* NewNode = BuyNewNode(x);
NewNode->next = phead;
phead = NewNode;
}
(三)单链表的尾删,头删
同样的操作
//单链表的尾删
void SingleListPopBack(SL** pphead)
{
assert(pphead && *phead);
SL* phead = *pphead;
//如果单链表只有一个结点
if (phead-> next == NULL)
{
free(phead);
phead = NULL;
}
else
{
//需要遍历查找链表尾部
SL* pcur = phead;
SL* prev = NULL;
while (pcur->next)
{
prev = pcur;
pcur = pcur->next;
}
// pcur pcur->next
prev->next = NULL;
free(pcur->next);
pcur->next = NULL;
}
}
//单链表的头删
void SingleListPopFront(SL** pphead)
{
assert(pphead && *pphead);
SL* phead = *pphead;
// phead phead->next;
SL* next = phead->next;
free(phead);
phead = next;
}
(四)单链表的查找,删除,销毁
//单链表的查找
SL* FindSingleList(SL* phead, SLDataType x)
{
assert(phead);
SL* pcur = phead;
while (pcur)
{
if (pcur->val == x)
return pcur;
pcur = pcur->next;
}
return NULL;
}
//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead && pos);
//pos就是头结点
if (pos == *pphead)
{
SLTPopFront(pphead);
}
else {
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
//prev pos pos->next
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
//单链表的销毁
void SListDestroy(SLTNode** pphead)
{
SLTNode* pcur = *pphead;
while (pcur)
{
SLTNode* next = pcur->next;
free(pcur);
pcur = next;
}
*pphead = NULL;
}