概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表
中的指针链接次序实现的 。
struct SListNode
{
int val;
struct SListNode* next;
};
test.h(包括所有程序的头文件和函数的声明)
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data; //节点数据
struct SListNode* next; //指针保存下⼀个节点的地址
}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** pphead, 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);
test.c(代码运行测试)
#include"test.h"
void test()
{
SLTNode* plist = NULL;
//尾插
SLTPushBack(&plist, 1);
SLTPushBack(&plist, 2);
SLTPushBack(&plist, 3);
SLTPushBack(&plist, 4);
//打印
SLTPrint(plist);
//头插
SLTPushFront(&plist, 11);
SLTPrint(plist);
//尾删
SLTPopBack(&plist);
SLTPrint(plist);
//头删
SLTPopFront(&plist);
SLTPrint(plist);
//在指定位置之前插入
SLTInsert(&plist, SLTFind(&plist, 3),20);
SLTPrint(plist);
//在指定位置之后插⼊数据
SLTInsertAfter(SLTFind(&plist, 3), 20);
SLTPrint(plist);
//删除pos结点
SLTErase(&plist,SLTFind(&plist,3));
SLTPrint(plist);
//删除pos结点后一个结点
SLTEraseAfter(SLTFind(&plist,3));
SLTPrint(plist);
//结点销毁
SListDesTroy(&plist);
SLTPrint(plist);
}
int main()
{
test();
return 0;
}
move.c
#include"test.h"
//结点创建
SLTNode* SLBuyNode(int x)
{
SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));
node->data = x;
node->next = NULL;
return node;
}
//打印链表
void SLTPrint(SLTNode* phead)//此时仅需一级指针即可实现程序
{
SLTNode* pcur = phead;
while (pcur)
{
printf("%d -> ", pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
node
(即调用SLBuyNode
函数);pcur
代替pphead
进行while循环,当pcur
的下一个结点位为NULL时,则说明pcur
为链表的末尾node
结点插入到最后即可void SLTPushBack(SLTNode** pphead, SLTDataType x)
{ //此时需要二级指针,因为链表需要被修改,应当传址调用
assert(pphead);
SLTNode* node = SLBuyNode(x);
if (*pphead == NULL)
{
*pphead = node;
return ;
}
SLTNode* pcur = *pphead;
while (pcur->next)
{
pcur = pcur->next;
}
pcur->next = node;
}
node
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
SLTNode* node = SLBuyNode(x);
node->next = *pphead;
*pphead = node;
}
pphead
和*pphead
都不能为空*pphead
进行free
后置空;若链表不止一个结点,需要创建两个结构体指针,分别为prev
和ptail
,prev
的作用是指向ptail
的前一个结点,ptail
的作用则是确定最后一个结点的位置prev
的next
指向ptail
的next
,再将ptail
进行free
后置空即可void SLTPopBack(SLTNode** pphead)
{
assert(pphead && *pphead);
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
return ;
}
SLTNode* prev = *pphead;
SLTNode* ptail = *pphead;
while (ptail->next)
{
prev = ptail;
ptail=ptail->next;
}
prev->next = ptail->next;
free(ptail);
ptail = NULL;
}
pphead
和*pphead
不为空del
代表要删除的结点位置(即为pphead
的位置)*pphead
指向*pphead
的next
即可,最后将待删除的del
指针free
后置空。void SLTPopFront(SLTNode** pphead)
{
assert(*pphead && pphead);
SLTNode* del = *pphead;
*pphead = (*pphead)->next;
free(del);
del = NULL;
}
pphead
不为空pcur
代替pphead
进行遍历,当pcur
的data
值与x
相等时,即可返回pcur
;若遍历完一遍还没找到,则返回NULL
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
assert(pphead);
SLTNode* pcur = *pphead;
while (pcur)
{
if (pcur->data == x)
{
return pcur;
}
pcur = pcur->next;
}
return NULL;
}
pphead、*pphead、pos
不为空node
和进行遍历的结构体指针prev
prev
的next
等于pos
时则退出遍历prev
的next
指向node
,node
的next
指向pos
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
assert(pphead && *pphead);
assert(pos);
SLTNode* node = SLBuyNode(x);
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev=prev->next;
}
prev->next = node;
node->next = pos;
}
pos
不为空node
,然后将node
的next
指向pos
的next
,pos
的next
指向node
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
assert(pos);
SLTNode* node = SLBuyNode(x);
node->next = pos->next;//
pos->next = node;//需要注意这两行代码不能交换顺序,否则node无法与pos的下一个结点进行连接
}
pos、pphead、*pphead
不为空pos
为头结点或者链表只要一个结点时,*pphead
等于*pphead
的next
,将pos
进行free
后置空即可pcur
,当pcur
的next
等于pos
时退出循环,将pcur
的next
指向pos
的next
,再将pos
进行free
即可void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pos && pphead && *pphead);
if (pos == *pphead)
{
*pphead = (*pphead)->next;
free(pos);
pos = NULL;
return;
}
SLTNode* pcur = *pphead;
while (pcur->next != pos)
{
pcur = pcur->next;
}
pcur->next = pos->next;
free(pos);
pos = NULL;
}
pos、pos->next
不为空del
,注意赋值为pos->next
而不是pos
pos
的next
指向del
的next
,将del
进行free
置空void SLTEraseAfter(SLTNode* pos)
{
assert(pos && pos->next);
SLTNode* del = pos->next;
pos->next = del->next;
free(del);
del = NULL;
}
pphead
不为空pcur
代替pphead
循环,pcur
等于NULL
则退出循环next
,作用是指向pcur
的next
,让pcur
进行free
后,再将pcur
赋值为next
,如此循环将链表销毁void SListDesTroy(SLTNode** pphead)
{
assert(pphead);
SLTNode* pcur = *pphead;
while (pcur)
{
SLTNode* next = pcur->next;
free(pcur);
pcur = next;
}
*pphead = NULL;
}