本篇文章我们用Go封装一个介入式的双向链表,目的是将链表的实现和具体元素解耦。文章参考自:https://github.com/brewlin/net-protocol

1.元素的接口

type Element interface {
Next() Element
Prev() Element
SetNext(Element)
SetPrev(Element)
}

2.链表的封装

type List struct {
head Element
tail Element
}

3.链表的操作

// Reset 清空List
func (l *List) Reset() {
l.head = nil
l.tail = nil
} // Empty 判断List是否为空
func (l *List) Empty() bool {
return l.head == nil
} // Front 返回第一个元素
func (l *List) Front() Element {
return l.head
} // Back 返回最后一个元素
func (l *List) Back() Element {
return l.tail
} // PushFront 插入元素到列头
func (l *List) PushFront(e Element) {
e.SetNext(l.head)
e.SetPrev(nil) if l.head != nil {
l.head.SetPrev(e)
} else {
l.tail = e
} l.head = e
} // PushBack 插入元素到列尾
func (l *List) PushBack(e Element) {
e.SetNext(nil)
e.SetPrev(l.tail) if l.tail != nil {
l.tail.SetNext(e)
} else {
l.head = e
} l.tail = e
} // PushBackList 插入一个list到列尾,并清空这个list
func (l *List) PushBackList(m *List) {
if l.head == nil {
l.head = m.head
l.tail = m.tail
} else if m.head != nil {
l.tail.SetNext(m.head)
m.head.SetPrev(l.tail) l.tail = m.tail
} m.head = nil
m.tail = nil
} // InsertAfter 在b后插入e
func (l *List) InsertAfter(b, e Element) {
a := b.Next()
e.SetNext(a)
e.SetPrev(b)
b.SetNext(e) if a != nil {
a.SetPrev(e)
} else {
l.tail = e
}
} // InsertBefore 在a前插入e
func (l *List) InsertBefore(a, e Element) {
b := a.Prev()
e.SetNext(a)
e.SetPrev(b)
a.SetPrev(e) if b != nil {
b.SetNext(e)
} else {
l.head = e
}
} // Remove 移除e
func (l *List) Remove(e Element) {
prev := e.Prev()
next := e.Next() if prev != nil {
prev.SetNext(next)
} else {
l.head = next
} if next != nil {
next.SetPrev(prev)
} else {
l.tail = prev
}
}

4.元素接口的实现

type Entry struct {
next Element
prev Element
} func (e *Entry) Next() Element {
return e.next
} func (e *Entry) Prev() Element {
return e.prev
} func (e *Entry) SetNext(elem Element) {
e.next = elem
} func (e *Entry) SetPrev(elem Element) {
e.prev = elem
}

5.使用示例

我们只需在结构体中用匿名字段继承Entry,就可以将其作为链表上的元素进行插入删除操作。

type Card struct {
Entry
num int
} func main() {
var list List
for i := 0; i < 10; i++ {
list.PushBack(&Card{num:i})
} for !list.Empty() {
e := list.Front()
fmt.Println(e.(*Card).num)
list.Remove(e)
}
}

最新文章

  1. 阿里巴巴分布式服务框架dubbo学习笔记
  2. Codeforces Round #375 (Div. 2) F. st-Spanning Tree
  3. Html - 涟漪特效
  4. mvc理念和thinkphp的语法特征 thinkphp引入模板
  5. IntelliJ IDEA 学习(六)内存设置
  6. Android上下左右滑动,显示底层布局
  7. oracle初始安装大小
  8. 团队作业10——项目复审与事后分析(Beta阶段)
  9. win 10 和 CentOS 7 双系统安装
  10. 带你深入理解STL之Deque容器
  11. [转] 2016 JavaScript 发展现状大调查
  12. angularjs学习第五天笔记(第二篇:表单验证升级篇)
  13. ZH奶酪:Python中range和xrange的区别
  14. Docker多主机网络 OpenvSwitch
  15. 有效Log4j按指定级别定向输出日志到指定的输出文件地址配置Threshold,log4j中如何屏蔽父logger输出源rootlogger的additivity配置,log4j向多个文件记录日志
  16. CentOS下MySQL的彻底卸载
  17. Asp.netMVC中地址后缀使用.html,jsp等404错误解决
  18. Mysql 会导致锁表的语法
  19. Android AIDL的用法
  20. CentOS 7运维管理笔记(12)----PHP页面失去焦点后变成空白的解决方法

热门文章

  1. docker05-dockerfile
  2. JAVA虚拟机08--垃圾回收--HotSpot的算法实现细节
  3. Vue 注册全局组件的方式
  4. JavaScript 如何验证 URL
  5. 02#Web 实战:实现树形控件
  6. PyOpenGL的安装与错误解决
  7. 开源分布式任务调度系统就选:DolphinScheduler
  8. springboot加入cloud,并注册到nacos
  9. ding抓回放
  10. 关于js对象的键