刨析数据结构(二)

🌈个人主页:小田爱学编程
🔥 系列专栏:数据结构————"带你无脑刨析"
🏆🏆关注博主,随时获取更多关于数据结构的优质内容!🏆🏆


😀欢迎来到小田代码世界~
😁 喜欢的小伙伴记得一键三连哦 ૮(˶ᵔ ᵕ ᵔ˶)ა


一.线性表的链式储存

链表:线性表的链式储存方式,逻辑结构不一定连续,物理结构不一定连续

描述:由数据域和指针域组成

🌏头结点:点是为了操作方便而设立的,放在第一个元素结点之前,不保存任何有意义的数据

🌏头节点:即为指向第一个节点的地址 

🔥链表分类:八种

👨‍🚀 以单链表(不带头单向不循环链表)

 二.单链表

1.优缺点

🔥任意位置插入删除,时间复杂度小
🔥没有增容问题,插入一个开辟一个空间

🔥不支持随机访问

2.创建

//定义链表
typedef int SLTDataType;//数值域
//链表是由节点组成
typedef struct SListNode
{
	SLTDataType data;//int data
	struct  SListNode* next;//它用来存储当前节点的下一个节点的地址
}SLTNode;//typedef struct SListNode SLTNode;

3.打印

void SLTPrint(SLTNode* phead) {
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}
SLTNode* plist = node1;
SLTPrint(plist);

 

3.申请空间

SLTNode* SLTBuyNode(SLTDataType x) {
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL) {
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

4.增加元素

尾插:

void SLTPushBack(SLTNode** pphead, SLTDataType x) {
	assert(pphead);

	SLTNode* newnode = SLTBuyNode(x);

	//链表为空,新节点作为phead
	if (*pphead == NULL) {
		*pphead = newnode;
		return;
	}
	//链表不为空,找尾节点
	SLTNode* ptail = *pphead;
	while (ptail->next)
	{
		ptail = ptail->next;
	}
	//ptail就是尾节点
	ptail->next = newnode;
}

头插:

void SLTPushFront(SLTNode** pphead, SLTDataType x) {
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);

	//newnode *pphead
	newnode->next = *pphead;
	*pphead = newnode;
}

在指定位置插入

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) {
	assert(pphead);
	assert(pos);
	//要加上链表不能为空
	assert(*pphead);

	SLTNode* newnode = SLTBuyNode(x);
	//pos刚好是头结点
	if (pos == *pphead) {
		//头插
		SLTPushFront(pphead, x);
		return;
	}

	//pos不是头结点的情况
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	//prev -> newnode -> pos
	prev->next = newnode;
	newnode->next = pos;
}

5.删除元素

 尾删

void SLTPopBack(SLTNode** pphead) {
	assert(pphead);
	//链表不能为空
	assert(*pphead);
	//链表不为空
	//链表只有一个节点,有多个节点
	if ((*pphead)->next == NULL) {
		free(*pphead);
		*pphead = NULL;
		return;
	}
	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;
	while (ptail->next)
	{
		prev = ptail;
		ptail = ptail->next;
	}
	prev->next = NULL;
	//销毁尾结点
	free(ptail);
	ptail = NULL;
}

 头删

void SLTPopFront(SLTNode** pphead) {
	assert(pphead);
	//链表不能为空
	assert(*pphead);
	//让第二个节点成为新的头
	//把旧的头结点释放掉
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

🔥指定位置删除:注意删除的逻辑

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos) {
	assert(pphead);
	assert(*pphead);
	assert(pos);

	//pos刚好是头结点,没有前驱节点,执行头删
	if (*pphead == pos) {
		//头删
		SLTPopFront(pphead);
		return;
	}

	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	//prev pos pos->next
	prev->next = pos->next;
	free(pos);
	pos = NULL;
}
void SLTEraseAfter(SLTNode* pos) {
	assert(pos);
	//pos->next不能为空
	assert(pos->next);

	//pos  pos->next  pos->next->next
	SLTNode* del = pos->next;
	pos->next = pos->next->next;
	free(del);
	del = NULL;
}

6.修改元素

//给一个数据,找到这个数据所在的节点,并用新数据修改
void SListChangeDate(SLTNode*pphead, SLTDataType x, SLTDataType y)
//不需要改变节点的地址,所以值传递即可 
//x是查找的数据,y是新的数据,用来修改查找的数据                                              
{
	SLTNode*cru = pphead;
	while (cru != NULL)//如果没有节点,根本不会进入循环去找
	{
		if (cru->data == x)
		{
			cru->data = y;
			break;//修改完数据后,就跳出循环
		}
		else
		{
			cru = cru->next;
		}
	}
	if (cru == NULL)//如果循环完单链表,没有找到要修改的那个数据
	{
		printf("要修改的数据不存在,请重新修改数据\n");
	}
	else
	{
		printf("修改成功\n");
	}
}

7.查找元素

SLTNode* SLTFind(SLTNode** pphead, SLTDataType x) {
	assert(pphead);
	//遍历链表 
	SLTNode* pcur = *pphead;
	while (pcur) //pcur != NULL
	{
		if (pcur->data == x) {
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	return NULL;
}

8.销毁链表

void SListDesTroy(SLTNode** pphead) {
	assert(pphead);
	assert(*pphead);

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

三.双向链表

1.注意

🔥带头双向循环链表

🔥当链表中只要头节点的时候,为空链表

🔥头节点是不能删除的,指向可以改变

🔥不需要改变头节点的指向,不需要传二级指针

🔥二级指针对实参会产生影响 

 2.创建

typedef int LTDataType;
typedef struct ListNode {
	LTDataType data;
	struct ListNode* prev;
	struct ListNode* next;
}LTNode;

3.打印

LTNode* LTInit() {
	LTNode* phead = LTBuyNode(-1);
	return phead;
}

4.增加元素

尾插(不需要找尾操作

//尾插
void LTPushBack(LTNode* phead, LTDataType x) {
	assert(phead);
	LTNode* newnode = LTBuyNode(x);
	//phead phead->prev(ptail)  newnode
	newnode->next = phead;
	newnode->prev = phead->prev;

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

 头插

//头插
void LTPushFront(LTNode* phead, LTDataType x) {
	assert(phead);

	LTNode* newnode = LTBuyNode(x);
	//phead newnode phead->next
	newnode->next = phead->next;
	newnode->prev = phead;

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

任意位置插入

//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x) {
	assert(pos);
	LTNode* newnode = LTBuyNode(x);
	//pos newnode pos->next
	newnode->next = pos->next;
	newnode->prev = pos;

	pos->next->prev = newnode;
	pos->next = newnode;
}
//删除pos位置的数据
void LTErase(LTNode* pos) {
	assert(pos);

	//pos->prev pos  pos->next
	pos->next->prev = pos->prev;
	pos->prev->next = pos->next;

	free(pos);
	pos = NULL;
}

5.删除元素

头删

void LTPopFront(LTNode* phead) {
	assert(phead);
	assert(phead->next != phead);

	LTNode* del = phead->next;
	LTNode* next = del->next;

	//phead del next
	next->prev = phead;
	phead->next = next;

	free(del);
	del = NULL;
}

 尾删

void LTPopBack(LTNode* phead) {
	assert(phead);
	//链表为空:只有一个哨兵位节点
	assert(phead->next != phead);

	LTNode* del = phead->prev;
	LTNode* prev = del->prev;

	prev->next = phead;
	phead->prev = prev;

	free(del);
	del = NULL;
}

 任意位置删除

void LTErase(LTNode* pos) {
	assert(pos);

	//pos->prev pos  pos->next
	pos->next->prev = pos->prev;
	pos->prev->next = pos->next;

	free(pos);
	pos = NULL;
}

6.修改元素

void DeleteNode(LTNode** pHead, LTNode* toBeDeleted) {
    if (pHead == NULL || toBeDeleted == NULL) {
        return;
    }

    LTNode* head = *pHead;

    // 要删除的节点是头节点
    if (head == toBeDeleted) {
        *pHead = toBeDeleted->next;
    }
    
    // 调整前驱节点的next指针
    if (toBeDeleted->prev != NULL) {
        toBeDeleted->prev->next = toBeDeleted->next;
    }
    
    // 调整后继节点的prev指针
    if (toBeDeleted->next != NULL) {
        toBeDeleted->next->prev = toBeDeleted->prev;
    }
    
    free(toBeDeleted);
}

7.查找元素

LTNode* LTFind(LTNode* phead, LTDataType x) {
	assert(phead);
	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		if (pcur->data == x) {
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

8.销毁链表

void LTDesTroy(LTNode* phead) {
	//哨兵位不能为空
	assert(phead);

	LTNode* pcur = phead->next;
	while (pcur != phead)
	{
		LTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	//链表中只有一个哨兵位
	free(phead);
	phead = NULL;
}

🥇这是博主年前的最后一篇文章哦,年后再继续更新,年后会开启新的刷题专栏!😊

🥇还有不到不到一周就过年喽!祝大家新的一年财源滚滚,学习进步,身体健康,咱们明年见! 

 🎁🎁🎁今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下,您的支持就是我前进的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/366134.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

d3dcompiler_47.dll是什么文件,如何解决找不到d3dcompiler_47.dll文件

d3dcompiler_47.dll是一个属于微软DirectX组件的动态链接库文件,它是Direct3D编译器的一部分,主要用于在Windows操作系统中编译和运行Direct3D 11应用程序和游戏。当你在电脑上尝试打开某些依赖Direct3D图形技术的软件或游戏时,如果系统找不到…

Flume搭建

压缩包版本:apache-flume-1.9.0-bin.tar 百度盘链接:https://pan.baidu.com/s/1ZhSiePUye9ax7TW5XbfWdw 提取码:ieks 1.解压 tar -zxvf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/ 2. 修改文件名 [rootbigdata1 opt]…

基于SpringBoot Vue超市管理系统

大家好✌!我是Dwzun。很高兴你能来阅读我,我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结,还为大家分享优质的实战项目,本人在Java项目开发领域有多年的经验,陆续会更新更多优质的Java实战项目&#x…

Codeforces Round 169 (Div. 2) D 异或最大值 二进制

题目&#xff1a; Problem - 276D - Codeforces 思路&#xff1a; l < r 1. l r &#xff0c;异或的结果为0 2. l < r &#xff08;注意&#xff1a;二进制位中&#xff0c;某一位是1,这一位后面的全是1&#xff0c;也没这个1大&#xff0c;比如1000 > 0111&…

HCIP-Datacom(H12-821)81-90题解析

有需要完整题库的同学可以私信博主&#xff0c;博主看到会回复将文件发给你&#xff01;&#xff08;麻烦各位同学给博主推文点赞关注和收藏哦&#xff09; 81、在状态检测防火墙中&#xff0c;开启状态检测机制时&#xff0c;三次握手的第二个报文(SYNACK)到达防火墙的时候如…

最新!2024顶级SCI优化!TTAO-CNN-BiGRU-MSA三角拓扑聚合优化、双向GRU融合注意力的多变量回归预测程序!

适用平台&#xff1a;Matlab 2023版及以上 TTOA三角聚合优化算法&#xff0c;将在2024年3月正式发表在中科院1区顶级SCI期刊《Expert Systems with Applications》上。 该算法提出时间极短&#xff0c;目前以及近期内不会有套用这个算法的文献。新年伊始&#xff0c;尽快拿下…

什么是在线教育,在线教育系统开源版本搭建教程

引言 随着数字化时代的到来&#xff0c;教育领域也在经历着一场深刻的变革。在线教育作为一种新兴的教育形式&#xff0c;正在以其灵活性和便利性受到越来越多人的关注和青睐。本文将介绍在线教育的概念&#xff0c;并提供基于开源版本的在线教育系统搭建教程&#xff0c;让教…

Docker容器引擎(5)

目录 一.docker-compose docker-compose的三大概念&#xff1a; yaml文件格式&#xff1a; json文件格式&#xff1a; docker-compose 配置模板文件常用的字段&#xff1a; 二.Docker Compose 环境安装&#xff1a; 查看版本&#xff1a; 准备好nginx 的dockerfile的文…

mysql本地数据库连接失败?

情景&#xff1a;mysql本地连接失败&#xff0c;账号密码都没问题。 原因&#xff1a;本地mysql服务没有启动 解决方案&#xff1a; 1、进入本地mysql安装的bin目录下D:\mysql-8.0.35-winx64\mysql-8.0.35-winx64\bin&#xff08;我的&#xff09;&#xff1b; 2、执行net st…

Android使用ScrollView导致鼠标点击事件无效

平台 测试平台: RK3288 Android8.1RK3588 Android 12 问题 首先, 这个问题的前提是, 使用的输入设备是**鼠标**, 普通的触摸屏并不会出现这个问题. 大致的流程是APP的UI布局中采用ScrollView作为根容器, 之后添加各类子控件, 在一起准备就绪后, 使用鼠标进行功能测试, 出现…

【Oracle云】OCI DevOps Services 教程 (3) - 创建自动化部署流水线【CD流水线】

欢迎来到【Oracle云】OCI DevOps Services教程的第三部分&#xff01;在这一部分中&#xff0c;我们将介绍如何在OCI上创建自动化部署流水线&#xff0c;也称为持续部署&#xff08;CD&#xff09;流水线。OCI DevOps Services提供了一套标准的构建工具&#xff0c;帮助我们简化…

解决WARNING: IPv4 forwarding is disabled. Networking will not work的具体操作步骤

IPv4转发禁用警告&#xff1a;网络无法正常工作 在使用网络连接的过程中&#xff0c;我们可能遇到警告消息“WARNING: IPv4 forwarding is disabled. Networking will not work”&#xff08;警告&#xff1a;IPv4转发已禁用&#xff0c;网络将无法正常工作&#xff09;。这个…

2.2号作业

一 1.A 2. A 3. A 4. D 5. D 6. B 7. A 8. C 9. A 10. 二 1. 42 2. cerr 3. cout <<"\n" 4. 5 5. 0 6. 7. 20 8. 1.50 9. ssi2 i…

UE4学习笔记 FPS游戏制作2 制作第一人称控制器

文章目录 章节目标前置概念Rotator与Vector&#xff1a;roll与yaw与pitch 添加按键输入蓝图结构区域1区域2区域3区域4 章节目标 本章节将实现FPS基础移动 前置概念 Rotator与Vector&#xff1a; Vector是用向量表示方向&#xff0c;UE中玩家的正前方是本地坐标系的(1,0,0)&…

ARM架构可视化ROS消息方案部署

ARM架构可视化ROS消息方案部署 三种方案, 1. webviz 2. foxglove 3. rosviz 注: web要用firefox, chromimum用不了, 可能是因为取消了时间同步机制的原因 先说三种方案的优劣, webviz 延迟比较高, 但是部署相对简单, foxglove 部署比较费劲, 但是效果不错, 延迟低, 本文会尽…

k8s kubeadm部署安装详解

目录 kubeadm部署流程简述 环境准备 步骤简述 关闭 防火墙规则、selinux、swap交换 修改主机名 配置节点之间的主机名解析 调整内核参数 所有节点安装docker 安装依赖组件 配置Docker 所有节点安装kubeadm&#xff0c;kubelet和kubectl 定义kubernetes源并指定版本…

带大家做一个,易上手的家常芹菜炒腊肉

起锅 放入腊肉 加入清水 水包裹住腊肉即可 盖上盖子煮15分钟 一把芹菜 芹菜切段 清水洗干净 15分钟后 捞出腊肉 将腊肉切片 一块生姜 两瓣蒜 将蒜切片 单独装起来 生姜切片 和三个干辣椒装一起 起锅 下腊肉 不要放油 腊肉够油了 翻炒开后 倒入生姜 干辣椒 翻炒个一分…

STM32CAN2进入bus off 模式

工作遇到的问题记录 无人机CAN2整个进不了中断&#xff0c;通过查看寄存器判定出CAN节点进入了bus off mode 为何进入bus off &#xff0c;最后通过示波器看到整个CAN2总线波形就不对&#xff0c;总线出现了错误 Busoff的产生是一定是因为节点自身识别到自己发送错误&#xff…

Modbus协议学习第七篇之libmodbus库API介绍(modbus_write_bits等)

写在前面 在第六篇中我们介绍了基于libmodbus库的演示代码&#xff0c;那本篇博客就详细介绍一下第六篇的代码中使用的基于该库的API函数。另各位读者&#xff0c;Modbus相关知识受众较少&#xff0c;如果觉得我的专栏文章有帮助&#xff0c;请一定点个赞&#xff0c;在此跪谢&…

oracle19C 密码包含特殊字符@ 导致ORA-12154

oracle 19C 密码包含特殊字符 出现登录失败&#xff0c;针对此问题一次说个明白 ORA-12154: TNS:could not resolve the connect identifier specified Oracle 19c之前密码是可以包含特殊字符&#xff0c;但是如果包含特殊字符需要双引号 比如oracle11g 正常 如果密码包含特殊…
最新文章