【数据结构】- 教你一步完美应对面试官让你10分钟内实现带头双向循环链表(下)

news2024/10/6 8:39:55

文章目录

  • 前言
  • 🌟一、面试官让你十分钟内实现带头双向循环链表
  • 🌟二、对链表的清晰认知
  • 🌟三、根据上述步骤简单实现
    • 🌏3.1结构:
    • 🌏3.2查找(LTFind)+LTErase+LTInsert:
    • 🌏3.3头插:
      • 💫3.3.1代码:
    • 🌏3.4尾插:
      • 💫3.4.1代码:
    • 🌏3.5头删:
      • 💫3.5.1代码:
    • 🌏3.6尾删:
      • 💫3.6.1代码:
    • 🌏3.7释放链表:
  • 🌟四、完整代码
  • 😽总结


前言

👧个人主页:@小沈熬夜秃头中୧⍤⃝❅
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:数据结构
🔑本章内容:[数据结构]—链表之带头双向循环链表
送给各位💌:不能因为没有掌声就丢掉自信 大起大落谁都有 拍拍灰尘继续走
欢迎 评论📝 +点赞👍 +收藏😽 +关注💞哦~


🌟一、面试官让你十分钟内实现带头双向循环链表

对于刚学链表的小白来说十分钟内实现一个带头双向循环链表是有点困难的,那有什么办法可以完成这个任务呢?别担心下面教你一步来实现。

🌟二、对链表的清晰认知

对于实现这个链表,首先结构是必须要写的,然后是初始化,而最重要的一个地方就是LTInsert(在pos位置之前插入)和LTErase(删除pos位置的值) 最后我们在头插 尾插 头删 尾删中复用就可以了最后再加上一个释放链表

🌟三、根据上述步骤简单实现

🌏3.1结构:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

typedef int LTDataType;

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

LTNode* LTInit();
void LTPrint(LTNode* phead);
void LTPushFront(LTNode* phead,LTDataType x);
void LTPushBack(LTNode* phead,LTDataType x);
void LTPopFront(LTNode* phead);
void LTPopBack(LTNode* phead);
LTNode* LTFind(LTNode* phead, LTDataType x);
void LTInsert(LTNode* pos, LTDataType x);
void LTErase(LTNode* pos);
void LTDestroy(LTNode* phead);

🌏3.2查找(LTFind)+LTErase+LTInsert:

不太懂这部分代码的宝贝可以看上一章

请添加图片描述
【数据结构】- 几个步骤教你认识并实现一个链表之带头(哨兵位)双向循环链表(上)
【数据结构】- 几个步骤教你认识并实现一个链表之带头(哨兵位)双向循环链表(中)

//LTFind
LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//LTInsert
void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = BuyLTNode(x);
	LTNode* Prev = pos->prev;
	Prev->next = newnode;
	newnode->prev = Prev;
	pos->prev = newnode;
	newnode->next = pos;
}
//LTErase
void LTErase(LTNode* pos)
{
	LTNode* Prev = pos->prev;
	LTNode* Next = pos->next;
	Prev->next = Next;
	Next->prev = Prev;
	free(pos);
}

🌏3.3头插:

💫3.3.1代码:

void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTInsert(phead->next , x);
}

🌏3.4尾插:

💫3.4.1代码:

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTInsert(phead, x);
}

🌏3.5头删:

💫3.5.1代码:

void LTPopFront(LTNode* phead)
{
	assert(phead);
	LTErase(phead->next);
}

🌏3.6尾删:

💫3.6.1代码:

void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));
	LTErase(phead->prev);
}

🌏3.7释放链表:

void LTDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

🌟四、完整代码

//List.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>

typedef int LTDataType;

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

LTNode* LTInit();
void LTPrint(LTNode* phead);
void LTPushFront(LTNode* phead,LTDataType x);
void LTPushBack(LTNode* phead,LTDataType x);
void LTPopFront(LTNode* phead);
void LTPopBack(LTNode* phead);
LTNode* LTFind(LTNode* phead, LTDataType x);
void LTInsert(LTNode* pos, LTDataType x);
void LTErase(LTNode* pos);
void LTDestroy(LTNode* phead);

//List.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
bool LTEmpty(LTNode* phead)
{
	assert(phead);
	return phead->next == phead;
}
LTNode* BuyLTNode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
	}
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}
LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}
void LTPrint(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	printf("guard<==>");
	while (phead != cur)
	{
		printf("%d==>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}
LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = BuyLTNode(x);
	LTNode* Prev = pos->prev;
	Prev->next = newnode;
	newnode->prev = Prev;
	pos->prev = newnode;
	newnode->next = pos;
}
void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTInsert(phead->next , x);
}
void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTInsert(phead, x);
}
void LTErase(LTNode* pos)
{
	LTNode* Prev = pos->prev;
	LTNode* Next = pos->next;
	Prev->next = Next;
	Next->prev = Prev;
	free(pos);
}
void LTPopFront(LTNode* phead)
{
	assert(phead);
	LTErase(phead->next);
}
void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));
	LTErase(phead->prev);
}
void LTDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

//Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
void TestList()
{
	LTNode* plist = LTInit();
	//LTPushFront(plist, 1);
	//LTPushFront(plist, 2);
	//LTPushFront(plist, 3);
	//LTPushFront(plist, 4);
	LTPushBack(plist, 1);
	LTPushBack(plist, 2);
	LTPushBack(plist, 3);
	LTPushBack(plist, 4);
	LTPrint(plist);
	/*LTNode* pos = LTFind(plist,1);
	if (pos)
	{
		LTInsert(pos, 30);
	}
	LTPrint(plist);*/
	/*LTNode* pos = LTFind(plist, 3);
	if (pos)
	{
		LTErase(pos, 30);
	}
	LTPrint(plist);*/
	//LTPopFront(plist);
	//LTPopFront(plist);
	//LTPrint(plist);
	LTPopBack(plist);
	LTPopBack(plist);
	LTPrint(plist);

}
int main()
{
	TestList();
	return 0;
}


😽总结

请添加图片描述
😽总体来说上面这种代码是比较优化的同时不会花费太多时间,简单易懂
😽Ending,今天的链表之带头双向循环链表(下)的内容就到此结束啦~,如果后续想了解更多,就请关注我吧,一键三连哦 ~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么要做计划跟踪:没有计划,就没有控制

日常工作中&#xff0c;我们每天都被大量的信息和任务填满&#xff0c;常常由于任务繁冗复杂&#xff0c;让人陷入一种无所适从的状态。 我们经常会看到很多如何安排工作计划的教程&#xff0c;比如&#xff1a; 要把大的项目分解为小目标&#xff0c;小目目标再分解为日常任务…

【技术干货】PCB焊盘设计之问题详解

SMT的组装质量与PCB焊盘设计有直接的关系&#xff0c;焊盘的大小比例十分重要。如果PCB焊盘设计正确&#xff0c;贴装时少量的歪斜可以再次回流焊纠正(称为自定位或自校正效应)&#xff0c;相反&#xff0c;如果PCB焊盘设计不正确&#xff0c;即使贴装位置十分准确&#xff0c;…

十分钟教你搭建类似ChatGPT的安卓应用程序

大家好&#xff0c;我是易安&#xff01; Chat GPT 是当今著名的人工智能工具&#xff0c;就像聊天机器人一样。Chat GPT会回答发送给它的所有查询。今天&#xff0c;我将通过集成 OpenAI API (ChatGPT)构建一个简单的类似 ChatGPT 的 android 应用程序&#xff0c;我们可以在其…

【docker_centos7】docker在centos7中如何安装??

Docker &#xff1f;&#xff1f;&#xff1f;What&#xff1f;&#xff1f;&#xff1f; Docker是一种开源的容器化平台&#xff0c;可以让开发者轻松地构建、打包、运输和部署应用程序。Docker容器是轻量级的、可移植的、自包含的软件包&#xff0c;其中包含了应用程序和其所…

Pytorch pth 格式转ONNX 格式

目录 背景介绍 安装依赖库 转换成onnx 格式 ONNX 转换成TensorRT 格式 背景介绍 PyTorch 训练的模型&#xff0c;需要在Jetson nano 上部署&#xff0c;jetson 原生提供了TensorRT 的支持&#xff0c;所以一个比较好的方式是把它转换成ONNX 格式&#xff0c;然后在通过ONNX …

给Debian 11系统,添加右键时,使用其它程序打开】

VS Code 添加到文件管理器的右键菜单中 在 Debian 系统中&#xff0c;nautilus-actions 软件包已经被移除了。因此&#xff0c;如果你想将 VS Code 添加到文件管理器的右键菜单中&#xff0c;你需要使用 nautilus-admin 工具。下面是详细步骤&#xff1a; 打开终端应用程序。运…

弃用 Docker 后!哪几种超好用的容器工具能替代?

2020 年底&#xff0c;Kubernetes 发布了公告&#xff0c;官方宣布从 v1.24 开始停止对 Docker 的支持。然而&#xff0c;Kubernetes 弃用 docker 对我们的影响不应过于恐慌。 有以下几种工具可以替代 Docker &#xff1f;并且相比 Docker 都有哪些优点&#xff1f; containe…

JRebel插件热部署快速入门教程

文章目录 引入插件安装插件激活打开激活窗口激活插件 插件使用设置项目热更新热更新说明演示热更新 引入 Jrebel能够非常方便的帮助我们进行项目的热更新&#xff0c;尤其是前端也嵌在后端工程中的单体项目&#xff0c;热更新能减少一半的开发时间&#xff0c;这里我们演示一下…

分布式缓存Redis 面试突击

Redis分布式锁 单机版 关于 synchronized 和trylock的区别 前者 是 不见不散 我一定要等到你 后者是 过时不候 我尝试一下 获取不到就算了 可以设置一个时间 这个时间范围内获取不到就算了 用缓存两个目的&#xff1a;高性能与高并发 高性能&#xff1a;减少了查询…

使用Linkage Mapper制作环境连接图

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Linkage Mapper解密数字世界链接 文章目录 引言一. 简介1.1 Linkage Mapper 概述1.2 环境连接…

基于html+css的图展示55

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

DJ5-8 磁盘存储器的性能和调度

目录 5.8.1 磁盘性能简述 1、磁盘的结构和布局 2、磁盘的类型 3、磁盘数据的组织和格式 4、磁盘的访问过程 5、磁盘访问时间 5.8.2 磁盘调度算法 1、先来先服务 FCFS 2、最短寻道时间优先 SSTF 3、扫描算法&#xff08;电梯算法&#xff09;SCAN 4、循环扫描算法 …

4 IK分词器

4 IK分词器 4.1测试分词器 在添加文档时会进行分词&#xff0c;索引中存放的就是一个一个的词&#xff08;term&#xff09;&#xff0c;当你去搜索时就是拿关键字去匹配词&#xff0c;最终 找到词关联的文档。 测试当前索引库使用的分词器&#xff1a; post 发送&#xff…

Python计算语义分割模型的评价指标

目录 一、混淆矩阵 二、分类指标 1、Accuracy(准确率&#xff09; 2、Precision&#xff08;查准率&#xff09; 3、Recall &#xff08;查全率&#xff09; 4、F1-score 三、语义分割的评价指标 1、MPA(类别平均像素准确率) 2、IoU(交并比) 3、MIoU(平均交并比) 4…

STL-stack容器和queue容器

stack概念&#xff1a;stack是一种先进后出(First In Last Out,FILO)的数据结构&#xff0c;它只有一个出口 栈中只有顶端的元素才可以被外界使用&#xff0c;因此栈不允许有遍历行为 与queue相似&#xff0c;stack也是一个适配器类&#xff0c;它给底层vector提供了典型的栈接…

C语言——数组

哈喽&#xff0c;大家好&#xff0c;今天我们要学习的是数组的相关知识。 目录 1.什么是数组 2.一维数组 2.1一维数组的创建和初始化 2.2一维数组的使用 2.3一位数组在内存中的存储 3.二维数组 3.1二维数组的创建和初始化 4.2二维数组的使用 4.3二位数组在内存中的存储…

java安全编码规范(0)

JAVA安全编码标准 有这么一指导书&#xff0c;新手可以去看看&#xff0c;这里主要从实践总结&#xff0c;随时会更新。 主要从十个方面去了解下&#xff0c;实际上远远不只这些哦。 ​​​​​​​ 1、引用java security library 环境需求 Java 8Maven 3 a、编译jar包&a…

「锂」清思绪,触达未来 | 锂电池企业如何实现数字化破局?

锂电池制造的困局与破局 锂电池行业产业链的上游主要为正负极材料、电解液、电极基材、隔膜等领域的供应商&#xff1b;中游为电芯制造及封装行业&#xff1b;下游则主要是动力电池、消费电子等锂电池的应用领域。 图1&#xff1a;锂电池行业产业链 近年来&#xff0c;随着相…

虹科方案 | 适用于高压环境或潜在爆炸性环境的加速度计系统

PART 1 加速度系统 加速度计系统通常用于测量振动或运动。测量系统能够记录一个、两个或三个空间方向的运动。所实际使用的传感器是光纤传感器&#xff0c;可提供不受电磁干扰影响的可靠测量值。当然&#xff0c;这样的系统具有高可靠性&#xff0c;即使在不断变化的天气条件下…

转置卷积(Transposed Convolution)可视化过程

目录 1. 介绍2. 标准卷积3. 转置卷积4. 总结 1. 介绍 转置卷积&#xff08;Transposed Convolution&#xff09;经常也被称作反卷积&#xff0c;所谓反卷积即为通过标准卷积层生成的输出被反卷积&#xff0c;将得到原始输入。而转置卷积不按值反转标准卷积&#xff0c;而仅按维…