一. 单链表介绍
单链表结构简单,每个节点中仅存有一个数据和指向下一个节点的指针变量;实际中它更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
二. 单链表实现
1. 定义节点
先定义出单链表中每个节点的结构:
// 定义单链表所存储数据的类型
typedef int SLTDateType;
// 单链表节点的声明
struct SListNode
{
// 数据
SLTDateType _data;
// 指向下一个节点的指针
struct SListNode* _next;
};
2. 打印单链表
三. 完整代码
- SList.h:存放单链表的结构和相关操作函数的声明
- SList.cpp:存放单链表操作函数的定义
- Test.cpp:用于测试单链表
SList.h
#pragma once
//需要用到的库函数的头文件
#include<stdio.h>
#include<stdlib.h>
//链表数类型的重定义
typedef int SLTDateType;
//链表节点的声明
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
//PS:不在pos位置插入的原因:单链表不方便找到pos位置之前的节点,从而实现新节点和前面节点的相连
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
//PS:不在pos位置删除的原因:单链表不方便找到pos位置之前的节点,从而实现前后节点的相连
void SListEraseAfter(SListNode* pos);
// 单链表的销毁
void Destory(SListNode** pplist);
SList.c
#include"SList.h"
// 动态申请一个节点
static SListNode* BuySListNode(SLTDateType x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->data = x;
newnode->next = NULL;
//最后把申请出来的节点返回
return newnode;
}
// 单链表打印
void SListPrint(SListNode* plist)
{
//PS:若链表为空直接打印NULL
while (plist)
{
printf("%d->", plist->data);
plist = plist->next;
}
printf("NULL\n");
}
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{
//开辟一个新节点
SListNode* newnode = BuySListNode(x);
SListNode* cur = *pplist;
// 1.空链表的情况
if (!cur)
{
*pplist = newnode;
}
// 2.非空链表的情况
else
{
//寻找尾节点
while (cur->next)
{
cur = cur->next;
}
cur->next = newnode;
}
}
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
SListNode* newnode = BuySListNode(x);
//使新节点的next指向原来的第一个结点
newnode->next = *pplist;
//新节点为链表的第一个节点
*pplist = newnode;
}
// 单链表的尾删
void SListPopBack(SListNode** pplist)
{
SListNode* pre = NULL;//当前节点的前一个节点
SListNode* cur = *pplist;//当前节点
// 1.空链表的情况
if (!cur)
{
return;
}
// 2.非空链表的情况
//寻找尾节点
while (cur->next)
{
pre = cur;
cur = cur->next;
}
// 2.1只有一个节点的情况
if (!pre)
{
free(*pplist);
*pplist = NULL;
return;
}
// 2.2有两个及以上节点的情况
pre->next = NULL;
free(cur);
cur = NULL;
}
// 单链表头删
void SListPopFront(SListNode** pplist)
{
// 1.空链表的情况
if (!(*pplist))
{
return;
}
// 2.非空链表的情况
SListNode* next = (*pplist)->next;
free(*pplist);
*pplist = next;
}
// 单链表查找
//PS:修改的话由使用者查找到节点之后自己修改就行
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
//遍历链表
while (plist)
{
if (plist->data == x)
{
return plist;
}
plist = plist->next;
}
//空链表或者找不到就返回NULL
return NULL;
}
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
SListNode* newnode = (SListNode*)BuySListNode(x);
// 1.空链表的情况
if (!pos)
{
return;
}
// 2.非空链表的情况
else
{
newnode->next = pos->next;
pos->next = newnode;
}
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{
//空链表的情况
if (!pos)
{
return;
}
//非空链表的情况
SListNode* next = pos->next;
//若pos之后还有节点就删除
//没有的话就啥都不干
if (next)
{
pos->next = next->next;
free(next);
next = NULL;
}
}
// 单链表的销毁
void Destory(SListNode** pplist)
{
SListNode* cur=*pplist;
while(cur)
{
SLitsNOde* next=cur->next;
free(cur);
cur=next;
}
*pplist=NULL;
}
test.c
#include"SList.h"
int main()
{
//测试
SListNode* p = NULL;
SListPushBack(&p, 1);
SListPushBack(&p, 2);
SListPushBack(&p, 3);
SListEraseAfter(p);
SListEraseAfter(p);
SListPrint(p);
Destory(&p);
return 0;
}