链表的实现

链表的实现

在这里插入图片描述

注意:

  1. 在主函数中先创建一个结构体指针 plist 指向NULL,用来往后链表的一系列操作。

  2. 一共有三个文件test.c , SList.h , SList.c

  3. 如果想要修改plist需要传plist的地址,也就是二级指针。

代码如下

SList.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType val;
	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* phead, 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);

SList.c

申请节点

SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* tmp = (SLTNode*)malloc(sizeof(SLTNode));
	if (tmp == NULL)
	{
		perror("malloc:");
		return 0;
	}
	tmp->next = NULL;
	tmp->val = x;
	return tmp;
}

尾部插入

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
	//链表为空
	if (*pphead == NULL)
	{
		*pphead = SLTBuyNode(x);
	}
	//链表不为空
	else
	{
		SLTNode* cur = *pphead;
		while (cur->next)
		{
			cur = cur->next;
		}
        //此时cur是尾节点
		cur->next = SLTBuyNode(x);
	}
}
情况1:链表为空

在这里插入图片描述

直接让 plist 指向新创建的节点

情况2:链表不为空

在这里插入图片描述

先用循环找到尾节点,找到后让cur->next = 新的节点。

头部插入

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
    assert(pphead);
	SLTNode* cur = SLTBuyNode(x);
	cur->next = *pphead;
	*pphead = cur;
}

在这里插入图片描述

先定义一个指针 cur 让 cur 指向 newnode ,然后让新节点的 next 指向 *pphead ,再让 * phead指向cur。

尾部删除

void SLTPopBack(SLTNode** pphead)
{
    //链表不能为空
    assert(pphead && *pphead)
	//链表只有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* prev = *pphead;
		SLTNode* ptail = *pphead;
		//链表有多个节点,可以用prev->next->next,也可以用prev 和ptail
		while (ptail->next)
		{
			prev = ptail;
			ptail = ptail->next;
		}
		free(ptail);
		ptail = NULL;
		prev->next = NULL;
	}
}
情况1:链表只有一个节点

在这里插入图片描述

直接释放*pphead,然后置空。

情况2:链表有多个节点

在这里插入图片描述

只用尾指针 ptail 的话没有办法把上一个节点的next置空,虽然可以用prev->next->next来做,但是用双指针更加便于理解。
我们先定义两个指针 prev 和 ptail ,然后找到尾的同时也找到了尾的上一个,然后释放 patil ,让 ptail 和 prev->next 置空。

头部删除

void SLTPopFront(SLTNode** pphead)
{
    assert(pphead && *pphead)
	SLTNode* tmp = NULL;
	//SLTNode* cur = *pphead;
	//tmp = cur->next;
	//free(cur);
	//cur = tmp;
	//如果要修改plist 的值就不能用cur来修改,只能通过指向plist的指针(pphead)解引用才能改变plist的值
	tmp = (*pphead)->next;
	free(*pphead);
	*pphead = tmp;
}

注意的是头删会修改 plist 的值所以一定要用 *pphead,才能修改 plist 的值。

查找

SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->val == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

查找不许要修改头 plist 所以传的是一级指针,让指针cur遍历链表,找到了就返回当前地址,找不到就返回NULL。

在指定位置之前插入数据

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
    assert(pphead && *pphead);
    assert(pos);
	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		SLTNode* cur = *pphead;
		while ((cur->next) != pos)
		{
			cur = cur->next;
		}
		cur->next = SLTBuyNode(x);
		cur->next->next = pos;
	}
}
情况1:在第一个节点前插入

判断一下是不是在头节点前插入数据,如果是那么就直接调用头插。

情况2:非头插

在这里插入图片描述

先创建 cur 让cur找到 pos 的前一个节点,然后让cur指向新的节点,在让新的节点的next(cur->next->next)指向 pos,完成插入。

在指定位置之后插入数据

void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
    assert(pos);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

在这里插入图片描述

创建一个新的节点,让新的节点的 next 指向 pos 的 next ,再让 pos 的 next 指向新的节点。

删除pos节点

void SLTErase(SLTNode** pphead, SLTNode* pos)
{
    assert(pphead && *pphead);
	if (pos == *pphead)
	{
		SLTPopFront(pphead);
		return;
	}
	if (pos->next == NULL)
	{
		SLTPopBack(pphead);
		return;
	}

	SLTNode* cur = *pphead;
	while ((cur->next) != pos)
	{
		cur = cur->next;
	}
	SLTNode* tmp = pos->next;
	free(pos);
	cur->next = tmp;
}
情况1:头删,和尾删就直接调用
情况2:非头删尾删

在这里插入图片描述

先定义指针 cur 找到要删除位置pos 的前一个节点,再用 tmp 存储 pos 下一个节点,释放pos后让cur的next指向tmp。

删除pos之后的节点

void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);
    SLTNode* del = pos->next;
    pos->next = del->next;
    free(del);
    del = NULL;
}

要删除的为空就会报错
在这里插入图片描述

销毁链表

void SListDesTroy(SLTNode** pphead)
{
    assert(pphead && *pphead);
    
    
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

pphead指针和链表都不能为空。定义一个指针依次遍历链表来释放。

test.c

#include"SList.h"
void test1()
{
	SLTNode* plist = NULL;    //重要
	SLTPushBack(&plist,1);
	SLTPushBack(&plist,2);
	SLTPushBack(&plist,3);
	SLTPrint(plist);
	SListDesTroy(&plist);
}
int main()
{
	test1();
	return 0;
}
  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值