目录
1.介绍
实际中的链表种类非常多,如是否带头,是否循环,是否双向等
举例:
本次详细介绍:无头+单向+非循环链表增删查改实现
2.先构造链表(结构体)的框架,及介绍基本的函数
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data; // 存储节点的数据
struct SListNode* next; // 存储下一个节点的地址
}SListNode, SLN;
void SListPrint(SListNode* phead);//打印链表
void SListNode* BuySListNode(SList Node *phead);//构造一个新的节点
void SListPushBack(SListNode** pphead, SLTDataType x);//尾插
void SListPushFront(SListNode** pphead, SLTDataType x);//头插
void SListPopBack(SListNode** pphead);//尾删
void SListPopFront(SListNode** pphead);//头删
SListNode* SListFind(SListNode* phead, SLTDataType x);//查找
void SListInsert(SListNode** pphead, SListNode* pos, SLTDataType x);// 在pos位置之前插入
void SListErase(SListNode** pphead, SListNode* pos);// 删除pos 位置
void SListInsertAfter(SListNode* pos, SLTDataType x);// 在pos之后插入
void SListEraseAfter(SListNode* pos);// 删除pos位置后面的值
void SListDestroy(SListNode** pphead);//链表的销毁
3.函数的实现
3.1打印及新节点函数
SListNode* BuySListNode(SLTDataType x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
else
{
newnode->data = x;
newnode->next = NULL;
}
return newnode;//返回新节点的指针
}
void SListPrint(SListNode* phead)
{
SListNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
3.2头尾删,头尾插,函数的实现
void SListPushBack(SListNode** pphead, SLTDataType x)
{
assert(pphead);
SListNode* newnode = BuySListNode(x);
if (*pphead == NULL)
{
*pphead = newnode;//传2级指针是为了改变头节点
}
else
{
// 找尾
SListNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void SListPopBack(SListNode** pphead)
{
assert(pphead);
// 也可以暴力检查为空的情况
//assert(*pphead != NULL);
// 1、空
// 2、一个节点
// 3、多个节点
if (*pphead == NULL) // 温柔检查
{
return;
}
else if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
/*SListNode* prev = NULL;
SListNode* tail = *pphead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;*/
//或者:
SListNode* tail = *pphead;
while (tail->next->next != NULL)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
void SListPopFront(SListNode** pphead)
{
assert(pphead);
// 1、空
// 2、非空
if (*pphead == NULL)
{
return;
}
else
{
SListNode* next = (*pphead)->next;
free(*pphead);
*pphead = next;//改变头节点要用2级指针
}
}
void SListPushFront(SListNode** pphead, SLTDataType x)
{
assert(pphead);
SListNode* newnode = BuySListNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
3.3查找及在某位置的插入及删除
SListNode* SListFind(SListNode* phead, SLTDataType x)
{
SListNode* cur = phead;
while (cur != NULL)
{
if (cur->data == x)
{
return cur;//返回指针
}
cur = cur->next;
}
return NULL;
}
该函数用法:SListNode* pos = SListFind(slist, 3);
在该链表中查找value==3的节点,并返回该节点的地址
void SListInsert(SListNode** pphead, SListNode* pos, SLTDataType x)
{
assert(pphead);
assert(pos);
// 1、pos是第一个节点
// 2、pos不是第一个节点
if (pos == *pphead)
{
SListPushFront(pphead, x);
}
else
{
SListNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
SListNode* newnode = BuySListNode(x);
prev->next = newnode;
newnode->next = pos;
}
}
void SListErase(SListNode** pphead, SListNode* pos)
{
assert(pphead);
assert(pos);
if (*pphead == pos)
{
SListPopFront(pphead);
}
else
{
SListNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
void SListDestroy(SListNode** pphead)
{
assert(pphead);
SListNode* cur = *pphead;
while (cur)
{
SListNode* next = cur->next;
free(cur);
cur = next;
}
*pphead = NULL;
}