数据结构【Golang实现】(四)——双向循环链表
目录
- 0. 定义节点
- 1. IsEmpty()
- 2. Length()
- 3. AddFromHead()
- 4. AddFromTail()
- 5. Insert()
- 6. DeleteHead()
- 7. DeleteTail()
- 8. Remove()
- 9. RemoveByValue()
- 10. Contain()
- 11. Traverse()
0. 定义节点
type DLNode struct {Data anyPrev, Next *DLNode
}// DoublyLoopLinkedList 双向循环链表
type DoublyLoopLinkedList struct {headNode *DLNode
}
1. IsEmpty()
// IsEmpty 判断链表是否为空
func (l *DoublyLoopLinkedList) IsEmpty() bool {if l.headNode == nil {return true}return false
}
2. Length()
// Length 获取链表长度
func (l *DoublyLoopLinkedList) Length() int {if l.IsEmpty() {return 0}currentNode := l.headNodecount := 1for currentNode.Next != l.headNode {count++currentNode = currentNode.Next}return count
}
3. AddFromHead()
// AddFromHead 从双向循环链表头部增加节点
func (l *DoublyLoopLinkedList) AddFromHead(data any) {node := &DLNode{Data: data}if l.IsEmpty() {l.headNode = nodereturn}currentNode := l.headNodefor currentNode.Next != l.headNode { // 遍历到尾结点currentNode = currentNode.Next}currentNode.Next = nodel.headNode.Prev = nodenode.Prev = currentNodenode.Next = l.headNodel.headNode = node
}
4. AddFromTail()
// AddFromTail 从双向循环链表尾部增加节点
func (l *DoublyLoopLinkedList) AddFromTail(data any) {node := &DLNode{Data: data}if l.IsEmpty() {l.headNode = nodereturn}currentNode := l.headNodefor currentNode != l.headNode { // 遍历到尾结点currentNode = currentNode.Next}currentNode.Next = nodel.headNode.Prev = nodenode.Prev = currentNodenode.Next = l.headNode
}
5. Insert()
// Insert 从双向循环链表指定位置增加节点 下标从0开始
func (l *DoublyLoopLinkedList) Insert(position int, data any) {if position <= 0 {l.AddFromHead(data)return} else if position >= l.Length()-1 {l.AddFromTail(data)return} else {node := &DLNode{Data: data}count := 0currentNode := l.headNodefor count != position {count++currentNode = currentNode.Next}node.Next = currentNodenode.Prev = currentNode.PrevcurrentNode.Prev.Next = nodecurrentNode.Prev = node}
}
6. DeleteHead()
// DeleteHead 删除链表头结点
func (l *DoublyLoopLinkedList) DeleteHead() {if l.IsEmpty() {fmt.Println("Doubly Linked List is Empty")return}currentNode := l.headNodeif currentNode.Next == l.headNode { // 只有一个节点的情况l.headNode = nilreturn} else {for currentNode.Next != l.headNode { // 遍历到倒数第一个节点currentNode = currentNode.Next}currentNode.Next = l.headNode.Nextl.headNode.Next.Prev = currentNodel.headNode = l.headNode.Next}
}
7. DeleteTail()
// DeleteTail 删除链表尾结点
func (l *DoublyLoopLinkedList) DeleteTail() {if l.IsEmpty() {fmt.Println("Doubly Linked List is Empty")return}currentNode := l.headNodeif currentNode.Next == l.headNode { // 只有一个节点的情况l.headNode = nilreturn} else {for currentNode.Next != l.headNode {currentNode = currentNode.Next}currentNode.Prev.Next = l.headNodel.headNode.Prev = currentNode.Prev}
}
8. Remove()
// Remove 删除链表指定位置结点
func (l *DoublyLoopLinkedList) Remove(position int) {if position <= 0 {l.DeleteHead()return} else if position >= l.Length()-1 {l.DeleteTail()return} else {count := 0currentNode := l.headNodefor count != position {count++currentNode = currentNode.Next}currentNode.Prev.Next = currentNode.NextcurrentNode.Next.Prev = currentNode.Prev}
}
9. RemoveByValue()
// RemoveByValue 删除链表指定值的节点
func (l *DoublyLoopLinkedList) RemoveByValue(data any) {if l.IsEmpty() {fmt.Println("Doubly Linked List is Empty")return}currentNode := l.headNodeif currentNode.Data == data { // 比较头结点l.DeleteHead()return}for currentNode.Next != l.headNode { // 这里是跳过了头结点的if currentNode.Next.Data == data {currentNode.Next.Prev.Next = currentNode.Next.NextcurrentNode.Next.Next.Prev = currentNode.Next.Prevreturn} else {currentNode = currentNode.Next}}
}
10. Contain()
// Contain 查询双向循环链表是否包含某个节点
func (l *DoublyLoopLinkedList) Contain(data any) bool {if l.IsEmpty() {return false}currentNode := l.headNodefor currentNode.Next != l.headNode {if currentNode.Data == data {return true} else {currentNode = currentNode.Next}}if currentNode.Data == data {return true}return false
}
11. Traverse()
// Traverse 遍历双向循环链表
func (l *DoublyLoopLinkedList) Traverse() {if l.IsEmpty() {fmt.Println("Doubly Linked List is Empty")return}currentNode := l.headNodefor currentNode.Next != l.headNode {fmt.Printf("%v -> ", currentNode.Data)currentNode = currentNode.Next}fmt.Printf("%v\n", currentNode.Data)
}
相关文章:
数据结构【Golang实现】(四)——双向循环链表
目录0. 定义节点1. IsEmpty()2. Length()3. AddFromHead()4. AddFromTail()5. Insert()6. DeleteHead()7. DeleteTail()8. Remove()9. RemoveByValue()10. Contain()11. Traverse()0. 定义节点 type DLNode struct {Data anyPrev, Next *DLNode }// DoublyLoopLinkedLis…...

【Redis】高可用架构之哨兵模式 - Sentinel
Redis 高可用架构之哨兵模式 - Sentinel1. 前言2. Redis Sentinel 哨兵集群搭建2.1 一主两从2.2 三个哨兵3. Redis Sentinel 原理剖析3.1 什么哨兵模式3.2 哨兵机制的主要任务3.2.1 监控(1)每1s发送一次 PING 命令(2)PING 命令的回…...

图片的美白与美化
博主简介 博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c,Python,爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主,博主会继续更新的,…...

面试官:关于CPU你了解多少?
CPU是如何执行程序的? 程序执行的基本过程 第一步,CPU 读取「程序计数器」的值,这个值是指令的内存地址,然后 CPU 的「控制单元」操作「地址总线」指定需要访问的内存地址,接着通知内存设备准备数据,数据准…...
UI自动化测试-Selenium的使用
文章目录 1. 环境搭建1.1 入门示例1.2 元素操作常用方法1.3 浏览器操作常用方法1.4 获取元素信息常用方法1.5 鼠标操作常用方法1.6 键盘操作常用方法1.7 下拉选择框操作2. 元素定位2.1 id定位2.2 name定位2.3 class_name定位2.4 tag_name定位2.5 link_text定位2.6 partail_link…...

嵌入式学习笔记——STM32的USART相关寄存器介绍及其配置
文章目录前言USART的相关寄存器介绍状态寄存器:USARTX->SR具体位代表的含义实际代码数据寄存器 USARTX->DR波特率寄存器 USARTX->BRR控制寄存器 (USART_CR)控制寄存器1(USART_CR1)控制寄存器2(USART_CR2)GPIO…...

Android setContentView流程分析(一)
对于做Android App的小伙伴来说setContentView这个方法再熟悉不过了,那么有多少小伙伴知道它的调用到底做了多少事情呢?下面就让我们来看看它背后的故事吧? setContentView()方法将分为两节来讲: 第一节:如何获取De…...

doris数据库操作数字遇到的问题
关于doris数据库Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库,以极速易用的特点被人们所熟知,仅需亚秒级响应时间即可返回海量数据下的查询结果,不仅可以支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。…...

3.13文件的IO操作
一.文件1.定义文件一般指的是存储在硬盘上的普通文件形如:txt.jpg.mp4,rar等这些文件在计算机中,文件可能是一个广义的概念,不仅可以包含普通文件,还可以包含目录(也就是文件夹.把目录称为目录文件)在操作系统中,还会用文件来描述一些其他的硬件设备或者软件资源比如网卡,显示器…...

ffmpeg使用
1 下载FFmpeg安装 官网地址:https://www.ffmpeg.org/download.html#build-windows 进入网址,点击下面红框部分 点击下面范围进行下载,下载速度有点慢,等等吧! 下载成功后,解压后,复制bin的路…...
spark中的并行度(分区数)/分区器如何确定
源头RDD有自己的分区计算逻辑,一般没有分区器,并行度是根据分区算法自动计算的,RDD的compute函数中记录了数据如何而来,如何分区的hadoopRDD,根据XxxinputFormat.getInputSplits()来决定,比如默认的TextInputFormat将文…...

00后女生“云摆摊”两周赚1.5万,实体店转战线上真的能赚钱吗?
最近,山东临沂的00后女生利用小程序在线上“云摆摊”卖水果,两周赚1.5万,引发网友热议。不少人发出质疑的声音:年轻人不要有稳定的工作不做,去摆摊;网上开店成本低,开实体店结果就难说了&#x…...
华为OD机试题 - 最优资源分配(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:最优资源分配题目输入输出描述备注示例一输入输出说明示例二输入…...
利用python判断字符串是否为回文
1 问题 如何用python判断字符串是否为回文。 2 方法 用两个变量left,right模仿指针(一个指向第一个字符,一个指向最后一个字符),每比对成功一次,left向右移动一位,right向左移动一位,…...

GDB 调用之ptype、set variable
今天在公司的时候,排查一个问题,创建l3 lif 失败,查看各种日志发现是用key去创建的 lif失败了,日志里指示key为空,导致的创建失败。原因为一个结构体比基线的多了一些东西,导致版本不对,既而计算…...

并发编程---阻塞队列(五)
阻塞队列一 阻塞队列1.1.阻塞队列概念1.2.阻塞队列API案例1.2.1. ArrayBlockingQueue1.2.1.1.抛出异常1.2.1.2.返回布尔1.2.1.3.阻塞1.2.1.4.超时1.2.2.SynchronousQueue二 阻塞队列应用---生产者消费者2.1.传统模式案例代码结果案例问题---防止虚假唤醒2.2.⽣产者消费者防⽌虚…...
本科课程【计算机组成原理】实验1 - 输出ABCD程序的生成
大家好,我是【1+1=王】, 热爱java的计算机(人工智能)渣硕研究生在读。 如果你也对java、人工智能等技术感兴趣,欢迎关注,抱团交流进大厂!!! Good better best, never let it rest, until good is better, and better best. 近期会把自己本科阶段的一些课程设计、实验报…...

Java并发编程(2) —— 线程创建的方式与原理
一、Java线程创建的三种方式 1. 继承Thread类并重写run()方法 ///方法一:使用匿名内部类重写Thread的run()方法Thread t1 new Thread() {Overridepublic void run() {try {sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}log.debug("…...
你写的js性能有多差你知道吗 | js性能优化
性能的计算⽅式 确认⾃⼰需要关注的指标 常⻅的指标有: ⻚⾯总加载时间 load⾸屏时间⽩屏时间 代码 尝试⽤⼀个指令, 挂载在重要元素上, 当此元素inserted就上报 各个属性所代表的含义 connectStart, connectEnd 分别代表TCP建⽴连接和连接成功的时间节点。如果浏…...

线程的状态、状态之间的相互转换
目录 一、线程的状态 1. NEW 2. TERMINATED 3. RUNNABLE 4. TIMED_WAITING 5. BLOCKED 6. WAITING 二、线程状态转换 1. 线程状态转换简图 一、线程的状态 线程的状态一共有 6 种: NEW:安排了工作,还未开始行动(调用 st…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...