【数据结构】单链表的简单实现

这篇具有很好参考价值的文章主要介绍了【数据结构】单链表的简单实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

一、单链表的定义

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

【数据结构】单链表的简单实现,数据结构,c语言,算法

二、链表中数据元素的构成

每个元素本身由两部分组成:
1、本身的信息,称为"数据域"
2、指向直接后继的指针,称为"指针域"

【数据结构】单链表的简单实现,数据结构,c语言,算法

三、链表的基本操作

SeqList.h头文件代码如下

typedef int SLDatetype;
typedef struct SListNode
{
    SLDatetype val;//数据域
    struct SListNode* next;//指针域
}SListNode;

//打印链表
void SLTPrint(SListNode*phead);
//销毁链表
void SLTDestroy(SLNode** pphead);
//尾插
void SLTPushBack(SListNode** pphead,SLDatetype x);

//头插
void SLTPushFront(SListNode** pphead,SLDatetype x);

//尾删
void SLTPopBack(SListNode** pphead);

//头删
void SLTPopFront(SListNode** pphead);

//查找
SListNode*SLTFind(SListNode* plist,SLDatetype x);

//在pos前面插入
void SLTInsert(SListNode** pphead, SListNode* pos, SLDatetype x);
//在pos前面删除
void SLTErase(SListNode** pphead,SListNode* pos);

//在pos后面位置插入
void* SLTInsertAfter(SListNode* pos,SLDatetype x);
//在pos后面删除
void* SLTEraseAfter(,SListNode* pos)



四、单链表的功能实现

4.1 打印单链表

链表打印不需要断言的,链表和顺序表不同,当链表中没有元素时,链表为空链表,头指针指向的就是NULL了,所以断言就会出问题。

void SLTPrint(SListNode*phead)
{
	SListNode* tail=phead;
	//遍历链表
	while(tail->next!=NULL)
	{
		printf("%d->",tail->val);
		//同时更新tail
		tail=tail->next;
	}
	printf("NULL");
}

4.2、销毁链表

注意:销毁操作不允许直接free(phead),因为链表在物理结构上不是连续存放的,必须要一个结点一个结点去释放

void SLTDestroy(SLNode** pphead)
{
	//断言,防止传空指针
	assert(pphead);
	SLNode* cur = *pphead;
	//空链表不进循环
	while (cur)
	{
		SLNode* next = cur->next;
		//释放每一个结点
		free(cur);
		cur = next;
	}
	//最后记得一定要置空
	*pphead = NULL;
}

4.3、创建新结点

因为我们后面插入部分都需要创建结点,所以我们专门设计一个创建结点的功能函数,既方便又减少了重复代码。

SListNode* CreaetNode(SLDatetype x)
{
	SListNode* newnode=(SListNode*)malloc(sizeof(SListNode));
	//判断malloc是否开辟成功结点
	if(newnode==NULL)
	{
		//开辟失败直接退出程序
		printf("malloc fail");
		exit(-1);
	}
	newnode->val=x;
	newnode->next=NULL;
	return newnode;
}

4.4、单链表尾插

思想

【数据结构】单链表的简单实现,数据结构,c语言,算法

void SLTPushBack(SListNode**pphead,SLDatetype x)
{
	//断言,防止传空指针
	assert(pphead);
	//创建结点
	SListNode*newnode=CreatNode(x);
	if(*pphead==NULL)
	{
		*pphead=newnode;
	}
	else
	{
		SListNode*tail=*pphead;
		//找尾,指针为空不进循环
		while(tail->next!=NULL)
		{
			//更新tail
			tail=tail->next;
		}
		//指向新的结点
		tail->next=newnode;
	}
}

测试及测试结果
尾插

void Test1()
{
	SListNode*plist=NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPrint(plist);
}

【数据结构】单链表的简单实现,数据结构,c语言,算法

4.5、单链表头插

思想

【数据结构】单链表的简单实现,数据结构,c语言,算法

void SLTPushFront(SListNode** pphead, SLDatetype x)
{
	//断言,防止传过来的是空指针
	assert(pphead);
	SListNode*newnode=CreatNode(x);
	newnode->next=*pphead;
	*pphead=newnode;
}

测试及测试结果
头插

void Test2()
{
	SListNode* plist = NULL;
	SLTPushFront(&plist, 1);
	SLTPushFront(&plist, 2);
	SLTPushFront(&plist, 3);
	SLTPushFront(&plist, 4);
	SLTPrint(plist);
}

【数据结构】单链表的简单实现,数据结构,c语言,算法

4.6、单链表尾删

思想

【数据结构】单链表的简单实现,数据结构,c语言,算法

void SLTPopBack(SListNode** pphead)
{
	//断言,防止传过来空指针
	assert(pphead);
	//暴力检查法
	assert(*pphead);
	//一个结点
	if((*pphead)->==NULL)
	{
		free(*pphead);
		*pphead=NULL;
	}
	//多个结点
	else
	{
		//双指针,找尾
		SListNode*prve=NULL;
		SListNode*tail=*pphead;
		while(tail->next==NULL)
		{
			//tail始终在prev的前面
			prev=tail;
			//更新tail
			tail=tail->next;
		}
		//释放空间
		free(tail);
		//置空
		prve->next=NULL;
	}
}

测试及测试结果
我们直接在Test1的基础上测试尾删

void Test1()
{
	SListNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPrint(plist);//打印1、2、3、4
	
	SLTPopBack(&plist);//尾删一个
	SLTPrint(plist);//打印1、2 、3

	SLTPopBack(&plist);//尾删一个
	SLTPrint(plist);//1、 2

	SLTPopBack(&plist);//再删后面一个
	SLTPrint(plist);//1

	SLTPopBack(&plist);//删空了
	SLTPrint(plist);//打印NULL
}

【数据结构】单链表的简单实现,数据结构,c语言,算法

4.7、单链表的头删

思想

【数据结构】单链表的简单实现,数据结构,c语言,算法

void SLTPopFront(SListNode** pphead)
{
	assert(pphead);
	//多个结点
	SListNode*tmp=*pphead;
	*pphead=(*pphead)->next;
	//释放指向的空间
	free(tmp);
}

测试

void TestSLT2()
{
	SListNode* plist = NULL;
	SLTPushFront(&plist, 1);
	SLTPushFront(&plist, 2);
	SLTPushFront(&plist, 3);
	SLTPushFront(&plist, 4);
	SLTPrint(plist);//头插打印4->3->2->1->NULL

	SLTPopFront(&plist);//头删一个
	SLTPrint(plist);//3->2->1->NULL
}

4.8、单链表数据查找

从链表头结点开始遍历,依次对比链表中数据域的值是否等于x,等于返回该节点指针,若链表中找不到、不存在就返回空并退出程序。

SListNode* SLTFind(SListNode* phead, SLDateType x)
{
	//断言,防止传空指针
	assert(phead);
	SListNode* cur=phead;
	//遍历
	while (cur)
	{
		if (cur->val == x)
		{
			return cur;
		}
		else
		{
			cur=cur->next;
		}
	}
	return NULL;
}

4.9、在pos前面插入

思想

【数据结构】单链表的简单实现,数据结构,c语言,算法

void SLTInsert(SListNode**pphead,SListNode*pos,SLDatetype x)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if(*pphead==pos)
	{
		//头插
		SLTPushFront(pphead,x);
	}
	else
	{
		SListNode*prev=*pphead;
		while(prev->next!=pos)
		{
			prev=prev->next;
		}
		SListNode*newnode=CreatNode(x);
		prve->next=newnode;
		newnode->next=pos;
	}
}

测试及测试结果

void TestSLT3()
{
	SListNode* plist = NULL;
	SLTPushFront(&plist, 1);
	SLTPushFront(&plist, 2);
	SLTPushFront(&plist, 3);
	SLTPushFront(&plist, 4);
	SLTPrint(plist);

	SListNode* pos = SLTFind(plist, 4);
	SLTInsert(&plist, pos, 40);
	SLTPrint(plist);
	
	pos = SLTFind(plist, 2);
	SLTInsert(&plist, pos, 20);
}

【数据结构】单链表的简单实现,数据结构,c语言,算法


4.10、删除链表pos位置

思想

【数据结构】单链表的简单实现,数据结构,c语言,算法

void SLTErase(SListNode** pphead, SListNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if(*pphead==pos)
	{
		//头删
		SLTPopFront(pphead);
	}
	else
	{
		SListNode*prve=*pphead;
		while(prev->next=pos)
		{
			prev=prev->next;
		}
		prev->next=pos->next;
		free(pos);
		pos=NULL;
	}
}

测试及测试结果

void TestSLT4()
{
	SLNode* plist = NULL;
	//插入数据
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPrint(plist);

	SLNode* pos = SLTFind(plist, 1);
	SLTErase(&plist, pos);
	SLTPrint(plist);
	
	pos = SLTFind(plist, 3);
	SLTErase(&plist, pos);
	SLTPrint(plist);
}

【数据结构】单链表的简单实现,数据结构,c语言,算法

4.11、在链表pos后面插入

【数据结构】单链表的简单实现,数据结构,c语言,算法文章来源地址https://www.toymoban.com/news/detail-757545.html

void SLTInsertAfter(SListNode* pos, SLDateytype x)
{
	//断言,空指针NULL不能指向下一个结点
	assert(pos);
	SListNode* newnode = CreatNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

4.12、在链表pos后面删除

void SLTEraseAfter(SListNode* pos)
{
	assert(pos);
	//断言,如果pos是最后一个结点,就不用再删除了
	assert(pos->next);

	SListNode* tmp = pos->next;
	pos->next = pos->next->next;

	free(tmp);
	tmp = NULL;
}

总结

//打印
void SLTPrint(SListNode*phead)
{
	SListNode* tail=phead;
	//遍历链表
	while(tail->next!=NULL)
	{
		printf("%d->",tail->val);
		//同时更新tail
		tail=tail->next;
	}
	printf("NULL");
}
//销毁
void SLTDestroy(SLNode** pphead)
{
	//断言,防止传空指针
	assert(pphead);
	SLNode* cur = *pphead;
	//空链表不进循环
	while (cur)
	{
		SLNode* next = cur->next;
		//释放每一个结点
		free(cur);
		cur = next;
	}
	//最后记得一定要置空
	*pphead = NULL;
}
//创建结点
SListNode* CreaetNode(SLDatetype x)
{
	SListNode* newnode=(SListNode*)malloc(sizeof(SListNode));
	//判断malloc是否开辟成功结点
	if(newnode==NULL)
	{
		//开辟失败直接退出程序
		printf("malloc fail");
		exit(-1);
	}
	newnode->val=x;
	newnode->next=NULL;
	return newnode;
}
//尾插
void SLTPushBack(SListNode**pphead,SLDatetype x)
{
	//断言,防止传空指针
	assert(pphead);
	//创建结点
	SListNode*newnode=CreatNode(x);
	if(*pphead==NULL)
	{
		*pphead=newnode;
	}
	else
	{
		SListNode*tail=*pphead;
		//找尾,指针为空不进循环
		while(tail->next!=NULL)
		{
			//更新tail
			tail=tail->next;
		}
		//指向新的结点
		tail->next=newnode;
	}
}
//头插
void SLTPushFront(SListNode** pphead, SLDatetype x)
{
	//断言,防止传过来的是空指针
	assert(pphead);
	SListNode*newnode=CreatNode(x);
	newnode->next=*pphead;
	*pphead=newnode;
}
//尾删
void SLTPopBack(SListNode** pphead)
{
	//断言,防止传过来空指针
	assert(pphead);
	//暴力检查法
	assert(*pphead);
	//一个结点
	if((*pphead)->==NULL)
	{
		free(*pphead);
		*pphead=NULL;
	}
	//多个结点
	else
	{
		//双指针,找尾
		SListNode*prve=NULL;
		SListNode*tail=*pphead;
		while(tail->next==NULL)
		{
			//tail始终在prev的前面
			prev=tail;
			//更新tail
			tail=tail->next;
		}
		//释放空间
		free(tail);
		//置空
		prve->next=NULL;
	}
}
//头删
void SLTPopFront(SListNode** pphead)
{
	assert(pphead);
	//多个结点
	SListNode*tmp=*pphead;
	*pphead=(*pphead)->next;
	//释放指向的空间
	free(tmp);
}
//查找
SListNode* SLTFind(SListNode* phead, SLDateType x)
{
	//断言,防止传空指针
	assert(phead);
	SListNode* cur=phead;
	//遍历
	while (cur)
	{
		if (cur->val == x)
		{
			return cur;
		}
		else
		{
			cur=cur->next;
		}
	}
	return NULL;
}
//在pos前面插入
void SLTInsert(SListNode**pphead,SListNode*pos,SLDatetype x)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if(*pphead==pos)
	{
		//头插
		SLTPushFront(pphead,x);
	}
	else
	{
		SListNode*prev=*pphead;
		while(prev->next!=pos)
		{
			prev=prev->next;
		}
		SListNode*newnode=CreatNode(x);
		prve->next=newnode;
		newnode->next=pos;
	}
}
//删除pos位置
void SLTErase(SListNode** pphead, SListNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if(*pphead==pos)
	{
		//头删
		SLTPopFront(pphead);
	}
	else
	{
		SListNode*prve=*pphead;
		while(prev->next=pos)
		{
			prev=prev->next;
		}
		prev->next=pos->next;
		free(pos);
		pos=NULL;
	}
}
//在链表pos后面插入
void SLTInsertAfter(SListNode* pos, SLDateytype x)
{
	//断言,空指针NULL不能指向下一个结点
	assert(pos);
	SListNode* newnode = CreatNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
//在链表pos后面删除
void SLTEraseAfter(SListNode* pos)
{
	assert(pos);
	//断言,如果pos是最后一个结点,就不用再删除了
	assert(pos->next);

	SListNode* tmp = pos->next;
	pos->next = pos->next->next;

	free(tmp);
	tmp = NULL;
}

到了这里,关于【数据结构】单链表的简单实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【数据结构】C语言实现单链表的基本操作

    【数据结构】C语言实现单链表的基本操作

    大家好,很高兴又和大家见面啦!!! 在上一篇中,我们详细介绍了单链表的两种创建方式——头插法与尾插法,相信大家现在对这两种方式都已经掌握了。今天咱们将继续介绍单链表的基本操作——查找、插入与删除。在开始今天的内容之前,我们先通过尾插法创建一个单

    2024年02月03日
    浏览(47)
  • 【数据结构】单链表的增删查改(C语言实现)

    【数据结构】单链表的增删查改(C语言实现)

    在上一节中我们提到了顺序表有如下缺陷: 在头部/中间的插入与删除需要挪动数据,时间复杂度为O(N),效率低; 增容需要申请新空间,可能会拷贝数据,释放旧空间,会有不小的消耗; 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容

    2024年02月06日
    浏览(49)
  • 【数据结构】单链表的基本操作 (C语言版)

    【数据结构】单链表的基本操作 (C语言版)

    目录 一、单链表 1、单链表的定义: 2、单链表的优缺点: 二、单链表的基本操作算法(C语言) 1、宏定义 2、创建结构体 3、初始化 4、插入 4、求长度 5、清空 6、销毁  7、取值 8、查找 9、删除 10、头插法创建单链表 11、尾插法创建单链表 三、单链表的全部代码(C语言)

    2024年01月22日
    浏览(47)
  • 【数据结构】 循环单链表的基本操作 (C语言版)

    【数据结构】 循环单链表的基本操作 (C语言版)

    目录 一、循环单链表 1、循环单链表的定义: 2、循环单链表的优缺点: 二、循环单链表的基本操作算法(C语言)    1、宏定义  2、创建结构体 3、循环单链表的初始化  4、循环单链表的插入 5、求单链表长度 6、循环单链表的清空 7、循环单链表的销毁 8、循环单链表的取

    2024年01月22日
    浏览(47)
  • 【(数据结构)— 单链表的实现】

    【(数据结构)— 单链表的实现】

    概念: 链表是⼀种 物理存储结构上非连续、 非顺序的存储结构,数据元素的 逻辑顺序 是通过链表中的 指针链接 次序实现的 。 链表的结构跟⽕⻋⻋厢相似,淡季时⻋次的⻋厢会相应减少,旺季时⻋次的⻋厢会额外增加⼏节。只需要将⽕⻋⾥的某节⻋厢去掉/加上,不会影响

    2024年02月08日
    浏览(55)
  • 【数据结构】单链表的实现

    【数据结构】单链表的实现

    🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏:https://blog.csdn.net/vhhhbb/category_12211053.html         家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我

    2023年04月09日
    浏览(49)
  • 【数据结构】-- 单链表的实现

    【数据结构】-- 单链表的实现

    在前面我们学习了顺序表,顺序表在数组的基础上提供了很多现成的方法,方便了我们对数据的管理,但是我们也发现顺序表有着许多不足: 在处理大型的数据时,需要频繁的增容且在中间删除或插入数据时需要遍历顺序表,这些性质导致了顺序表的 效率较低 。这时我们就

    2024年04月27日
    浏览(63)
  • 【数据结构—单链表的实现】

    【数据结构—单链表的实现】

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 1. 链表的概念及结构 2. 单链表的实现 2.1单链表头文件——功能函数的定义 2.2单链表源文件——功能函数的实现 2.3 单链表源文件——功能的测试 3.具体的理解操作图 4. 链表的分类 总结 世上

    2024年02月05日
    浏览(54)
  • 【数据结构】单链表的层层实现!! !

    【数据结构】单链表的层层实现!! !

    关注小庄 顿顿解馋(●’◡’●) 上篇回顾 我们上篇学习了本质为数组的数据结构—顺序表,顺序表支持下标随机访问而且高速缓存命中率高,然而可能造成空间的浪费,同时增加数据时多次移动会造成效率低下,那有什么解决之法呢?这就得引入我们链表这种数据结构 概念

    2024年03月12日
    浏览(514)
  • 【数据结构】实现单链表的增删查

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

    链表类和节点类的定义: 图解: 从中间位置插入: 图解:假定index=2 尾插: 删除当前线性表中索引为index的元素,返回删除的元素值: 图解: 删除当前线性表中第一个值为element的元素: 删除当前线性表中所有值为element的元素: 将当前线性表中index位置的元素替换为eleme

    2024年02月14日
    浏览(455)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包