【数据结构】《动图演示》单链表实现

本文详细介绍了单链表的概念、结构,包括其分类(单向、双向、带头、不带头、循环、非循环),并实现了各种操作如头插、尾插、查找、删除和销毁,同时分析了pos处和pos后面操作的时间复杂度特点。

前言

数据结构的常见线性表,分别是顺序表,链表,栈,队列

本篇给大家带来单向无头链表的实现和讲解

为什么会有单链表?

  • 动态顺序表储存数据存会造成一定的消耗
  • 链表存储数据是按需扩容,不会造成空间浪费
  • 通常做复杂数据结构的子部分

等单链表的相关文章写完,之后就出一篇详细顺序表和单链表的区别


一、链表的概念和结构

1.1 概念

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

1.2 结构和存储

  • 逻辑结构
    在这里插入图片描述

  • 物理结构
    在这里插入图片描述

  1. 从上图可看出,链式结构在逻辑上是连续的,但是在物理上不一定连续,他们这种连续的结构主要是其指针域指向了下一个结点的地址。
  2. 现实中的结点一般都是从(heap)申请出来的。
  3. 从堆上申请空间,是按照一定的策略来分配的,两次申请的空间可以能连续,也可能不连续。比如连续:第一个结点地址是0x0023b11,下一个地址就是0x0023b15

二、链表的分类

2.1 单项和双向
在这里插入图片描述

2.2 带头和不带头
在这里插入图片描述

2.3 循环和非循环
在这里插入图片描述

综上所述以有8种链表,但是我们实际用的就**2种**

在这里插入图片描述

  1. 无头单向非循环链表:结构简单,一般不会单独用来存放数据。实际中更多是作为其他数据结构的子结构。如:哈希桶、图的领接表等等。另外这种结构在笔试面试中出现很多。

  2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。另外这个结构虽然复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。

三、单链表的实现

一般我们写一个项目的时候,一共包含3个文件。

  • 头文件.h:存放该项目所有需要的头文件,结构定义,函数声明。
  • 函数定义文件.c:函数的定义和实现
  • 测试文件.c:测试函数的功能

3.1 定义单链表的结构

一般定义结构前,我们会先重命名该结构的数据类型,因为这个结构可能会存放不止一种数据,可能会存放int、float、double等等,所以为了方便我们代码后期维护,重定义后只需要改变一处就可以了。

// 存放的数据类型
typedef int SListDataType;

单个节点包含两个部分:数据域(data)指针域(next)
在这里插入图片描述

  • data:存放结点的数据部分
  • next:存放下一个结点(结构体)的地址
// 单链表结点的定义
typedef struct SListNode	
{
   
   
	SListDataType data;			// 数据域
	struct SListNode* next;		// 指针域
}SListNode; 

在这里插入图片描述

这里的意思就是重命名,把sturct SListNode 命名为SListNode,大家可以看我们后面的代码我定义变量的使用,类型是SListNode,正常情况在c语言里是不行,必须要加
关键字struct+结构体名才可以定义,c++里面就不要加关键字。

3.2 创建一个结点

每次插入的时候,我们都需要写很多重复的代码,所以可以把创建节点写成一个函数,后面方便调用。

思路:

  1. 申请一块结点结构体大小的空间
  2. 对他进行判断,是否为NULL
  3. 把数据放到data
  4. next指向NULL
  5. 最后返回申请成功的结点
// 创建一个节点
SListNode* CreateSListNode(SListDataType x)
{
   
   
	// 申请一块空间
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));	
	// 判断是否为空
	if (newNode == NULL)
	{
   
   
		printf("new node falied!");
		exit(-1);
	}
	// 需要插入的数据放到data里
	newNode->data = x;
	// 该结点的next指向空
	newNode->next = NULL;
	// 返回申请的结点
	return newNode;
}

3.3 尾插

在这里插入图片描述
思路:

  1. 利用assert,防止实参传过来NULL,这是不是说链表地址,而是直接传NULL
  2. 调用刚才创建结点的函数
  3. 判断链表是否为空,分两种情况,1. 链表为空 2. 链表不为空
    为空就直接把创建的结点设为头节点,不为空就找尾,把尾结点的next指向新创建的结点
    在这里插入图片描述
// 尾插
void 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值