速学数据结构 | 手把手教你会单链表的构建方式

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


速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法

🎬 鸽芷咕:个人主页

 🔥 个人专栏: 《初阶数据结构》《C语言进阶篇》
⛺️生活的理想,就是为了理想的生活!

📋 前言

  🌈hello! 各位宝子们大家好啊!今天给大家带来的是初阶数据结构中单链表的构建方式,手把手教会你单链表
  ⛳️链表是指一种逻辑上是连在一起的数据结构,但是物理存储上却是分开的部分!是通过链表中的指针链接次序实现的一种数据结构!
  📚本期文章收录在《初阶数据结构》,大家有兴趣可以看看呐
  ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!

1. 什么是链表

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法

顺序表我们都知道有点类似数组,是在物理上一块连续存放的内存块!所以顺序表也叫 线性表 但是开辟必须需要连续的空间空间的浪费特别严重!

  • 所以就有链表这种数据结构,避免了空间的浪费。
  • 链表在逻辑上是连在一起但是内存块确实分布在不同位置的
  • 通过指针访问每个链表的节点

1.1 链表的物理结构

速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法
从这里可以看出:

   链表在逻辑上是连续的但是,物理上是单独分开的。由每一块的指针记录下一个节点的地址进行访问

🔥 注意

  • 现实中的节点一般都是在堆上申请出来的
  • 在堆上申请的空间,是编译器按照一定规则分配的,俩次申请的空间可能有时连续有时不连续。

1.2 链表的种类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  • 单向或者双向
    速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法

  • 带头或者不带头
    速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法

  • 循环或者非循环
    速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法

但是我们今天就先从简单的入手,先来实现一下单链表的结构!先从简单的下手。

  • 单链表结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2. 链表的实现

好了废话不多讲,下面我们就来到链表的实现过程。链表前面我们了解了不是一个连续的存储结构,S是利用指针来进行每个节点的访问。

  • 注:我们把链表里的每个内容叫做一个节点

速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法

一. SList.h 单链表的声明

3.1 定义链表结构

链表链表首先我们要先定义链表的结构,链表既有数据又要和下一个链表联系起来那么肯定是要使用结构体:

  • 来定义链表
  • 而内容需要一个 data 和 指向下一个节点的指针!
typedef  int  SLTDataType;
//定义链表结构
typedef	struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

3.2 单链表函数的声明

单链表要实现的功能其实也非常简单,和顺序表是一模一样的。增删改查等这些操作而我们只要把这些函数实现了,那么在刷关于链表的题的时候也就无非是这些操作的变形。

  • 下面我们就来看看单链表具体要实现的功能把!
//动态申请链表节点
SLTNode* BuySListNode(SLTDataType x);

//打印单链表
void SLTPrint(SLTNode* plist);

//单链表头插
void SLTPushFront(SLTNode** pplist,SLTDataType x);

//单链表尾插
void SLTPushBack(SLTNode** pplist, SLTDataType x);

//单链表头删
void SLTPopFront(SLTNode** pplist);

//单链表尾删
void SLTPopBack(SLTNode** pplist);

//查找节点
SLTNode* SLTFind(SLTNode* pplist, SLTDataType x);

//在pos以前插入x
void SLTInsert(SLTNode** pplist, SLTNode* pos, SLTDataType x);

// 在pos以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);

// 删除pos位置
void SLTErase(SLTNode** pplist, SLTNode* pos);

// 删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos);

// 单链表的销毁
void SListDestroy(SLTNode* pplist);

二. SList.h 单链表的定义

2.1 动态申请链表一个节点

前面我们把链表的基本结构定义好了那么接下来就申请节点了,这样我们才能进行链表的链接已经数据的存储!

  • 而开辟节点直接用 malloc 开辟空间然后赋值就好啦!
//动态申请链表节点
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc file");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

2.2 单链表打印

打印单链表也是一个十分简单的功能了,既然我们链表的每个节点的 next 存储的都是下一个节点那么直接循环访问就好啦!

  • 要注意控制好循环变量的结束条件
  • 和链表最后 NULL 的打印
//打印单链表
void SLTPrint(SLTNode* plist)
{
	SLTNode* cur = plist;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}

	printf("NULL\n");
}

2.3 单链表尾插

单链表的尾插也不是很难控制好着俩点就好了:

  • 第一个是 plist 为空的情况,直接尾插
  • 第二个是 plist 不为空的情况,循环找到尾直接尾插
//单链表尾插
void SLTPushBack(SLTNode** pplist, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	
	if (*pplist == NULL)
	{
		*pplist = newnode;
	}
	else
	{
		SLTNode* tail = *pplist;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = newnode;
	}
}

2.4 单链表的头插

这个可以说是最简单的部分了,只要让要 plist 指向 插入的节点,插入节点的 next 指向下一个节点。

  • 还要注意一下断言
//单链表头插
void SLTPushFront(SLTNode** pplist,SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);

	newnode->next = *pplist;
	*pplist = newnode;
}

2.5 单链表的尾删

单链表的头插尾插我们实现了下面就是单链表的尾删了。注意要控制好边界的几种情况就好了

  • 一个是链表只有一个节点的情况下直接删除
  • 还有一个是链表有多个节点需要遍历
//单链表尾删
void SLTPopBack(SLTNode** pplist)
{
	//非空判断
	assert(*pplist);
	SLTNode* tail = *pplist;
	
	
	if ((*pplist)->next == NULL)
	{
		free(*pplist);
		*pplist = NULL;
	}
	else
	{
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}

	 
		free(tail->next);
		tail->next = NULL;
	}

}

2.6 单链表头删

单链表的头删注意考虑俩总情况,一个是只有一个节点释放,一个是多个节点释放。

  • 在 assert 断言一下NULL链表就不删除
//单链表头删
void SLTPopFront(SLTNode** pplist)
{
	//非空判断
	assert(*pplist);

	SLTNode* newhead = (*pplist)->next;
	free(*pplist);
	*pplist = newhead;
}

2.7 单链表查找

为什么要先写单链表的查找呢,因为我们现实中通常不知道我们要删除或者插入的数在第一个点上所以需要先查找要删除或者插入的数到时候删除直接复用就好了。

  • 查找的话直接循环遍历就好了,如果找不到就返回空NULL。
//查找节点
SLTNode* SLTFind(SLTNode* plist, SLTDataType x)
{
	SLTNode* cur = plist;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}

	return NULL;
}

2.8 在pos之前插入x

和前面的删除一样,需要控制好不同的情况和 暴力检测一下 plist 传过来的是不是一个空指针。

  • 空指针就直接退出说明传错了
  • 还要注意遍历pos前一个节点
//在pos以前插入x
void SLTInsert(SLTNode** pplist, SLTNode* pos, SLTDataType x)
{
	assert(*pplist);
	assert(pos);
	

	if (pos == *pplist)
	{
		SLTPushFront(pplist,x);
	}
	else
	{
		SLTNode* prev = *pplist;

		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLTNode* newnode = BuySListNode(x);

		prev->next = newnode;
		newnode->next = pos;
	}
}

2.9 在pos之后插入x

这个就没在pos之前插入x那么复杂了可以根据指针找到下一个节点,然后删除pos的后一个节点

  • 将next 连接到pos的下下个节点上
// 在pos以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);

	if (pos->next == NULL)
	{
		pos->next = newnode;
	}
	else
	{
		SLTNode* next = pos->next->next;
		pos->next = newnode;
		newnode->next = next;
	}
}

2.10 删除pos位置

删除pos的位置就需要循环遍历pos,的前一个位置。然后进行 free 释放空间

  • 在把俩个节点关联起来就可以了

// 删除pos位置
void SLTErase(SLTNode** pplist, SLTNode* pos)
{
	assert(pplist);
	assert(pos);

	if(*pplist == pos)
	{
		SLTPopFront(pplist);
	}
	else
	{
		SLTNode* prve = *pplist;
		while (prve->next != NULL)
		{
			prve = prve->next;
		}

		prve->next = pos->next;
		free(pos);
	}
}

2.11 删除pos的后一个位置

// 删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);

	assert(pos->next);
	
	SLTNode* posNext = pos->next;
	pos->next = posNext->next;
	free(posNext);
	posNext = NULL;

	
}

三. test.c 单链表的功能测试

这里博主就不给大家测试给大家写个样例,大家自己去试试增删查改哦!

void Test_SList2()
{
	SLTNode* plist = NULL;

	SLTPushFront(&plist, 1);
	SLTPushFront(&plist, 2);
	SLTPushFront(&plist, 3);
	SLTPushFront(&plist, 4);
	SLTPushFront(&plist, 5);
	SLTPrint(plist);
}
int main()
{
	Test_SLsit1();
	
}

📝全篇总结

✅ 归纳:
好了以上就是关于分支语句 链表 的所有知识点了,大家快下去练习练习吧!
  链表的介绍
  链表的结构
  链表的增删查改

☁️ 把本章的内容全部掌握,铁汁们就可以熟练应用switch语句啦!
看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注

💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
速学数据结构 | 手把手教你会单链表的构建方式,初阶数据结构,数据结构,机器学习,C++,算法文章来源地址https://www.toymoban.com/news/detail-713153.html

到了这里,关于速学数据结构 | 手把手教你会单链表的构建方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 数据结构之栈和队列 - 超详细的教程,手把手教你认识并运用栈和队列

    栈:后进先出 队列:先进先出 栈:是一种特殊的 线性表 , 只允许在固定的一端插入或者删除元素 ,一个栈包含了栈顶和栈底。只能在栈顶插入或者删除元素。 栈的底层 是由 数组 实现的。 栈遵循先入后出原则,也就是先插入的元素得到后面才能删除,后面插入的元素比

    2024年02月07日
    浏览(83)
  • 数据结构->顺序表实战指南,(手把手教会你拿捏数据结构顺序表)

    文章目录 ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青-CSDN博客 今天开始我们正式进入数据结构的学习了,这篇简单了解一下: 线性表的存储结构:顺序存储结构、链式存储结构; 顺序表的定义:用一段物理地址连

    2024年01月25日
    浏览(65)
  • 数据结构->手把手教入门栈与列队(基础)

    ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青-CSDN博客 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除 操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守 后

    2024年03月24日
    浏览(249)
  • 【数据结构】—堆详解(手把手带你用C语言实现)

                                            食用指南:本文在有C基础的情况下食用更佳                                          🔥 这就不得不推荐此专栏了: C语言                                        ♈️ 今日夜电波: 水星—今泉愛夏              

    2024年02月07日
    浏览(62)
  • 【初识数据结构】手把手教会你时间复杂度的计算方法

    前言   大家好啊,这里是幸麟 一名普通的大学牲 🧩希望可以不断的进步,因此也一直在学习 如果有写的不好或者写错的地方 欢迎在评论区指正 前言后的小前言 不知道在大家学习算法时有没有遇到这样一种情况,在看大佬题解或者讲解视频时 总能找到一个叫 时间复杂度

    2024年02月09日
    浏览(92)
  • 【数据结构】—手把手带你用C语言实现栈和队列(超详细!)

                                       食用指南:本文在有C基础的情况下食用更佳                                     🔥 这就不得不推荐此专栏了:C语言                                   ♈️ 今日夜电波:Tell me —milet                    

    2024年02月14日
    浏览(119)
  • 【数据结构】万字一文手把手解读哈希————(开/闭散列)解决哈希冲突完整详解(6)

    前言 大家好吖,欢迎来到 YY 滴 数据结构 系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《

    2024年02月04日
    浏览(127)
  • 数据库:如何安装SQL,手把手教你

    我们只选择两个: SQLEXPR_x64_CHS.exe SQLManagementStudio_x64_CHS.exe 如果你是32位系统就选择x86的(9102年了,应该都是64位的了吧)选中后下载到你经常保存文件的地方即可(这个地方并不是sql要安装的地方)。 全部下载后如图所示 正式安装 先安装SQL,再安装 SQL Management Studio 双击

    2024年01月16日
    浏览(78)
  • 手把手教你使用Segformer训练自己的数据

    使用Transformer进行语义分割的简单高效设计。 将 Transformer 与轻量级多层感知 (MLP) 解码器相结合,表现SOTA!性能优于SETR、Auto-Deeplab和OCRNet等网络 相比于ViT,Swin Transfomer计算复杂度大幅度降低,具有输入图像大小线性计算复杂度。Swin Transformer随着深度加深,逐渐合并图像块来

    2024年01月20日
    浏览(76)
  • 手把手教你配置MySQL数据库(图,文)

    下载 这是MySQL的官方下载地址 https://dev.mysql.com/downloads/ 既然我们是配置MySQL数据库,就选择下载MySQL的压缩文件  Download Archives 点击进入  然后我们选择第一个 MySQL Community Server  进入  接着选择我们需要的版本和系统,这次我们要在windows系统下配置MySQL 8.0 。 选好后下载第一

    2024年02月09日
    浏览(45)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包