【数据结构】单链表增删查改实现

一. 单链表介绍

在这里插入图片描述

单链表结构简单,每个节点中仅存有一个数据和指向下一个节点的指针变量;实际中它更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。

二. 单链表实现

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值