>🎊上文介绍了线性表的顺序存储结构——顺序表基本功能的实现方法。
>🎡本篇文章会为大家介绍线性表的链式存储结构中单链表基本功能的实现方法。
>🎁还请喜欢的朋友们三连支持!
目录
🎡一、准备工作
还是老样子,首先介绍一下需要用到的头文件、重命名
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLTDateType;//single linked list
💥注意:因为单链表是链式存储,所以在插入删除元素时只需要改变指针域指向即可,不需要扩充空间,所以无需定义链表容量,只要内存允许,链表可以无限长
🎡二、定义链表结构
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
🎡三、函数声明
//菜单
void meum();
//初始化链表
void InitList(SListNode** pplist);
//动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
//打印数据
void SListPrint(SListNode* plist);
//头插法
void SListPushFront(SListNode** pplist, SLTDateType x);
//尾插法
void SListPushBack(SListNode** pplist, SLTDateType x);
//头删法
void SListPopFront(SListNode** pplist);
//尾删法
void SListPopBack(SListNode** pplist);
//查找数据
SListNode* SListFind(SListNode* plist, SLTDateType x);
//在pos位置之后插入数据x
void SListInsertAfter(SListNode* pos, SLTDateType x);
//删除pos位置之后的数据
void SListEraseAfter(SListNode* pos);
//取出第pos个数据
SLTDateType GetElem(SListNode* plist, int pos);
//对链表数据进行升序排列
void ListSortUp(SListNode** pplist);
//清空单链表
void ClearList(SListNode** pplist);
//销毁单链表
void SListDestroy(SListNode** pplist);
//计算链表表长
int LengthList(SListNode* plist);
🎡四、基本操作的实现
✨1.初始化链表
实现原理:新建一个单链表结点,将指针域置为空
//初始化链表
void InitList(SListNode** pplist)
{
assert(pplist);
*pplist= (SListNode*)malloc(sizeof(SListNode));
if (*pplist == NULL)
{
perror("InitList malloc");
}
(*pplist)->next = NULL;
}
✨2.动态申请一个节点
//动态申请一个节点
SListNode* BuySListNode(SLTDateType x)
{
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
if (newnode == NULL)
{
perror("Newnode malloc");
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
✨3.输出链表
//打印数据
void SListPrint(SListNode* plist)
{
assert(plist);
SListNode* cur = plist->next;
while (cur != NULL)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
✨4.头插法插入元素
实现原理:创建一个新结点,将元素赋值到结点的数据域中,将头结点的指针域指向新结点,新节点的指针域指向原来头结点指向的地址
//头插法
void SListPushFront(SListNode** pplist, SLTDateType x)
{
assert(pplist);
SListNode* newnode = BuySListNode(x);
newnode->next = (*pplist)->next;
(*pplist)->next = newnode;
}
✨5.尾插法插入元素
实现原理:创建一个新结点,将元素赋值到结点的数据域中,将尾结点的指针域指向新结点,新节点的指针域置为空
//尾插法
void SListPushBack(SListNode** pplist, SLTDateType x)
{
assert(pplist);
SListNode* cur = *pplist;
while (cur->next)
cur = cur->next;
SListNode* newnode = BuySListNode(x);
newnode->next = cur->next;
cur->next = newnode;
}
✨6.在pos位置之后插入数据x
实现原理:找到要插入位置的前一个结点,改变该结点指针域的指向
//在pos位置之后插入数据x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
assert(pos);
SListNode* next = pos->next;
SListNode* newnode = BuySListNode(x);
pos->next = newnode;
newnode->next = next;
}
✨7.头删法
//头删法
void SListPopFront(SListNode** pplist)
{
assert(pplist);
if ((*pplist)->next == NULL)
{
printf("链表中无数据!\n");
return;
}
else
{
SListNode* cur = (*pplist)->next;
(*pplist)->next = cur->next;
free(cur);
cur = NULL;
}
}
✨8.尾删法
实现原理:找到要删除元素的前一个结点,改变该结点的指针域
//尾删法
void SListPopBack(SListNode** pplist)
{
assert(pplist);
if ((*pplist)->next == NULL)
{
printf("链表中无数据!\n");
return;
}
else
{
SListNode* cur = *pplist;
SListNode* node = (*pplist)->next;
while (node->next != NULL)
{
cur = cur->next;
node = node->next;
}
cur->next = NULL;
free(node);
node = NULL;
}
}
💥注意:因为单链表无法向前查找,所以指针cur用来存储前一个结点地址,便于进行删除操作
✨9.取出第pos个数据
//取出第pos个数据
SLTDateType GetElem(SListNode* plist, int pos)
{
assert(plist && pos > 0);
SListNode* cur = plist;
while (pos)
{
cur = cur->next;
pos--;
}
return cur->data;
}
✨10.查找元素
//查找数据
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
assert(plist);
SListNode* cur = plist->next;
while (cur)
{
if (cur->data == x) return cur;
else cur = cur->next;
}
return NULL;
}
✨11.对链表元素进行升序排序
实现原理:先将单链表的元素放到一个数组中,对数组进行排序后,再将元素依次放入到单链表的的数据域中
//对链表数据进行升序排列
void ListSortUp(SListNode** pplist)
{
assert(pplist);
int length = LengthList(*pplist);
if (length <= 1) return;
SLTDateType* arr = (SLTDateType*)malloc(sizeof(SLTDateType) * length);
if (arr == NULL)
{
perror("malloc");
}
//将链表中的元素放到数组中
for (int i = 0; i < length; i++)
{
arr[i] = GetElem(*pplist, i + 1);
}
//对数组元素进行升序排序
int i, j;
for (i = 0; i < length - 1; i++)
{
for (j = 0; j < length - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
SLTDateType tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
//将数组中的元素放回链表中
SListNode* cur = (*pplist)->next;
for (int i = 0; i < length; i++)
{
cur->data = arr[i];
cur = cur->next;
}
}
✨12.清空单链表
实现原理:依次释放所有结点,并将头结点指针域置为空
//清空单链表
void ClearList(SListNode** pplist)
{
assert(pplist);
SListNode* node = (*pplist)->next;
while (node != NULL)
{
SListNode* cur = node->next;
free(node);
node = cur;
}
(*pplist)->next = NULL;
}
✨13.销毁单链表
实现原理:从头指针开始,依次释放结点
//销毁单链表
void SListDestroy(SListNode** pplist)
{
ClearList(pplist);
free(*pplist);
*pplist = NULL;
}
✨14.计算链表表长
实现原理:遍历单链表,cur非空则length加一
//计算链表表长
int LengthList(SListNode* plist)
{
assert(plist);
SListNode* cur = plist->next;
int length = 0;
while (cur)
{
length++;
cur = cur->next;
}
return length;
}
好了,就介绍到这里,有问题的地方欢迎评论区留言,如果感觉有帮助,还请三连支持!!!
需要完整代码的朋友私我!