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双向链表源码走读相关推荐

  1. Apache Spark源码走读之16 -- spark repl实现详解

    欢迎转载,转载请注明出处,徽沪一郎. 概要 之所以对spark shell的内部实现产生兴趣全部缘于好奇代码的编译加载过程,scala是需要编译才能执行的语言,但提供的scala repl可以实现代码 ...

  2. spark on yarn yarn-client模式实现源码走读

    Spark版本2.4.0 在SparkContext的初始化过程中,将会根据配置的启动模式来选择不同的任务调度器TaskScheduler,而这个不同模式的实现也是在这里根据选择的TaskSchedu ...

  3. ConcurrentHashMap源码走读

    ConcurrentHashMap源码走读 文章目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 简介 在从JDK8开始,为了提高并发度,C ...

  4. JAVA进阶之路-CountDownLatch源码走读

    前言 本章用到了之前谈到的AQS,就是在该FIFO阻塞框架的基础上改造的,不理解的,可以去看JAVA进阶之路-AbstractQueuedSynchronizer(AQS)源码走读 用途 CountD ...

  5. 深度增强学习DDPG(Deep Deterministic Policy Gradient)算法源码走读

    原文链接:https://blog.csdn.net/jinzhuojun/article/details/82556127 本文是基于OpenAI推出deep reinforcement learn ...

  6. [redis 源码走读] 主从数据复制(上)

    阅读源码前,先了解 redis 主从复制的基本知识. 详细源码分析,请参考下一章:[redis 源码走读] 主从数据复制(下)

  7. golang gin框架源码分析(二)---- 渐入佳境 摸索Engine ServeHTTP访问前缀树真正原理

    文章目录 全系列总结博客链接 前引 golang gin框架源码分析(二)---- 渐入佳境 摸索Engine ServeHTTP访问前缀树真正远原理 1.再列示例代码 从示例代码入手 2.r.Run ...

  8. Webrtc从理论到实践七: 官方demo源码走读(peerconnection_server)

    系列文章目录 Webrtc从理论到实践一:初识 Webrtc从理论到实践二: 架构 Webrtc从理论到实践三: 角色 Webrtc从理论到实践四: 通信 Webrtc从理论到实践五: 编译webrt ...

  9. Golang Http Server源码阅读

    建议看这篇文章前先看一下net/http文档 http://golang.org/pkg/net/http/ net.http包里面有很多文件,都是和http协议相关的,比如设置cookie,head ...

最新文章

  1. WIDERFACE 数据集
  2. 【Pygame小游戏】这款休闲游戏你肯定了解过《开心消消乐》更新版本上线,好土好喜欢
  3. odata协议里filter操作自带的函数 - endswith
  4. 01-图像ROI区域获取
  5. 产品经理和程序员的黑话
  6. phpcms v9输出内容过滤html代码 - 代码篇
  7. [导入]ASP.NET Ajax程序设计第II卷:客户端Microsoft Ajax Library与异步通信层及源代码.zip(101.50 MB)...
  8. vue v-model指令
  9. 13. 在O(1)时间删除链表节点(C++版本)
  10. esxi 命令行查看设备
  11. sql server2008密钥
  12. 自定义流程gooflow.08 demo在线演示
  13. 【论文笔记】EagerMOT:3D Multi-Object Tracking via Sensor Fusion
  14. TDA4VM中各个CPU对应的名字
  15. 阿里云弹性云桌面安装失败问题解决记录(.net framework 4.6.2 or later:Error Code: 12029)
  16. 双击打开excel内容不显示而显示灰色解决方法
  17. 算法的时间复杂度详解
  18. 小福利,用excel制作旋风图,小狗图和漏斗图
  19. JS原生制作手风琴特效
  20. [转载]使用JDBC创建数据库对象

热门文章

  1. xxd命令转换二进制十六进制文件
  2. Shell调试Debug的三种方式
  3. python urllib3 request 无返回结果_python urllib request urlopen请求网页返回bytes类型
  4. 阿尔伯塔大学的计算机科学专业好吗,去阿尔伯塔大学留学这些专业千万不能错过!...
  5. jeecg集成积木报表错误_6688种玩法的电子积木,是什么体验?「中外玩具网测评」...
  6. 第19章,运维自动化之系统安装
  7. C语言实现的图的深度搜索与广度搜索程序
  8. centos 字体的修改
  9. layui table数据渲染页面+筛选医生+在筛选日期一条龙2
  10. solaris10默认防火墙软件ipfilter