Golang list双向链表源码走读
list概览
list为golang中的双向链表实现,存入list中的元素都会被封装成list中的节点放到双向链表中进行存储。
简单的list使用代码如下:
func main() {list := list.New()fmt.Println("list length is " + strconv.Itoa(list.Len()))list.PushBack(1)list.PushBack(2)list.PushBack(3)fmt.Println("list length is " + strconv.Itoa(list.Len()))for i := list.Front(); i != nil; i = i.Next() {fmt.Println(i.Value)}for i := list.Front(); i != nil; i = i.Next() {if i.Value == 2 {list.Remove(i)}}fmt.Println("***************")for i := list.Front(); i != nil; i = i.Next() {fmt.Println(i.Value)}
}
在上述代码中,简单的完成了对于list的初始化,元素的添加,list的遍历与元素的移除。可以看到,基于list的遍历都是基于元素的指针进行,这里的操作类似java中的LinkedList。
list的节点
type Element struct {next, prev *Elementlist *ListValue interface{}
}
从上面的代码可以看到,在list中,单个节点会被封装成Element存储在队列中,其中next与prev为节点前后的指针,list为该节点所处的list指针,value则来存放具体的值。这里的实现是与java中的LinkedList极为相似的,在java中的LinkedList,每个节点也被封装成了Node存储在链表中。
list本身的结构
type List struct {root Element len int
}
在List自身的结构体中,root作为根节点,虽然称为根节点,但是在具体的双向链表中,root节点实则将该双向链表连成了一个圈,通过其next可以得到链表中的首节点,而通过其prev则可以得到其尾节点,这里与java的LinkedList维护首尾两个节点的做法不同,更加高效。同时,只需要从根节点的next出发即可完成对于双向链表的遍历,直到通过next到达根节点为止。
而len则记录了当前双向链表的长度,当需要得到当前链表的长度的时候只需要返回len即可,同样在java的LinkedLis中也通过size记录了当前链表的长度。
list的初始化
func (l *List) Init() *List {l.root.next = &l.rootl.root.prev = &l.rootl.len = 0return l
}
list的初始化非常简单,将根节点的前后指针都指向自己,并初始化长度为0即可/
list的插入与移除
当双向链表中向链表尾部插入元素的时候,如上文所说,由于list中通过根节点的prev一直维护着尾节点,只需要将插入的值包装为list中的节点后插入到根节点的prev之前即可。
func (l *List) PushBack(v interface{}) *Element {l.lazyInit()return l.insertValue(v, l.root.prev)
}func (l *List) insert(e, at *Element) *Element {e.prev = ate.next = at.nexte.prev.next = ee.next.prev = ee.list = ll.len++return e
}func (l *List) insertValue(v interface{}, at *Element) *Element {return l.insert(&Element{Value: v}, at)
}
同样的,当需要将元素插入到队列的头部的时候,只需要将其包装成节点后插入到根节点的next即可。
而与java的LinkedList不同的是,当需要移除list当中的节点的时候,必须要传入需要移除的list中的节点才行。
func (l *List) Remove(e *Element) interface{} {if e.list == l {l.remove(e)}return e.Value
}func (l *List) remove(e *Element) *Element {e.prev.next = e.nexte.next.prev = e.preve.next = nil e.prev = nil e.list = nill.len--return e
}
相较于java的做法,这样的移除方式虽然存在一定的局限性,但是首先,由于节点本身存在指向所处list的指针,可以避免在错误的队列中移除对应的元素,同时不需要在移除前对整个链表进行遍历(当然在获取该节点的时候已经遍历过了),只需要将前后节点相连并将其next,pre置nil来防止内存泄漏即可。
Golang list双向链表源码走读相关推荐
- Apache Spark源码走读之16 -- spark repl实现详解
欢迎转载,转载请注明出处,徽沪一郎. 概要 之所以对spark shell的内部实现产生兴趣全部缘于好奇代码的编译加载过程,scala是需要编译才能执行的语言,但提供的scala repl可以实现代码 ...
- spark on yarn yarn-client模式实现源码走读
Spark版本2.4.0 在SparkContext的初始化过程中,将会根据配置的启动模式来选择不同的任务调度器TaskScheduler,而这个不同模式的实现也是在这里根据选择的TaskSchedu ...
- ConcurrentHashMap源码走读
ConcurrentHashMap源码走读 文章目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 简介 在从JDK8开始,为了提高并发度,C ...
- JAVA进阶之路-CountDownLatch源码走读
前言 本章用到了之前谈到的AQS,就是在该FIFO阻塞框架的基础上改造的,不理解的,可以去看JAVA进阶之路-AbstractQueuedSynchronizer(AQS)源码走读 用途 CountD ...
- 深度增强学习DDPG(Deep Deterministic Policy Gradient)算法源码走读
原文链接:https://blog.csdn.net/jinzhuojun/article/details/82556127 本文是基于OpenAI推出deep reinforcement learn ...
- [redis 源码走读] 主从数据复制(上)
阅读源码前,先了解 redis 主从复制的基本知识. 详细源码分析,请参考下一章:[redis 源码走读] 主从数据复制(下)
- golang gin框架源码分析(二)---- 渐入佳境 摸索Engine ServeHTTP访问前缀树真正原理
文章目录 全系列总结博客链接 前引 golang gin框架源码分析(二)---- 渐入佳境 摸索Engine ServeHTTP访问前缀树真正远原理 1.再列示例代码 从示例代码入手 2.r.Run ...
- Webrtc从理论到实践七: 官方demo源码走读(peerconnection_server)
系列文章目录 Webrtc从理论到实践一:初识 Webrtc从理论到实践二: 架构 Webrtc从理论到实践三: 角色 Webrtc从理论到实践四: 通信 Webrtc从理论到实践五: 编译webrt ...
- Golang Http Server源码阅读
建议看这篇文章前先看一下net/http文档 http://golang.org/pkg/net/http/ net.http包里面有很多文件,都是和http协议相关的,比如设置cookie,head ...
最新文章
- WIDERFACE 数据集
- 【Pygame小游戏】这款休闲游戏你肯定了解过《开心消消乐》更新版本上线,好土好喜欢
- odata协议里filter操作自带的函数 - endswith
- 01-图像ROI区域获取
- 产品经理和程序员的黑话
- phpcms v9输出内容过滤html代码 - 代码篇
- [导入]ASP.NET Ajax程序设计第II卷:客户端Microsoft Ajax Library与异步通信层及源代码.zip(101.50 MB)...
- vue v-model指令
- 13. 在O(1)时间删除链表节点(C++版本)
- esxi 命令行查看设备
- sql server2008密钥
- 自定义流程gooflow.08 demo在线演示
- 【论文笔记】EagerMOT:3D Multi-Object Tracking via Sensor Fusion
- TDA4VM中各个CPU对应的名字
- 阿里云弹性云桌面安装失败问题解决记录(.net framework 4.6.2 or later:Error Code: 12029)
- 双击打开excel内容不显示而显示灰色解决方法
- 算法的时间复杂度详解
- 小福利,用excel制作旋风图,小狗图和漏斗图
- JS原生制作手风琴特效
- [转载]使用JDBC创建数据库对象
热门文章
- xxd命令转换二进制十六进制文件
- Shell调试Debug的三种方式
- python urllib3 request 无返回结果_python urllib request urlopen请求网页返回bytes类型
- 阿尔伯塔大学的计算机科学专业好吗,去阿尔伯塔大学留学这些专业千万不能错过!...
- jeecg集成积木报表错误_6688种玩法的电子积木,是什么体验?「中外玩具网测评」...
- 第19章,运维自动化之系统安装
- C语言实现的图的深度搜索与广度搜索程序
- centos 字体的修改
- layui table数据渲染页面+筛选医生+在筛选日期一条龙2
- solaris10默认防火墙软件ipfilter