当前位置: 首页 > wzjs >正文

视频网站内容规划做企业培训的网站

视频网站内容规划,做企业培训的网站,特殊教育学校网站建设方案,荔枝直播app软件1、背景 鸽了很久很久的一个东西了…现在有时间了,还是来把它补齐一下。 双向链表,在 C 中经常使用到: [C系列] 54. list的介绍及使用 习题练手: 146. LRU 缓存 Github 代码仓库,欢迎 start!&#xf…

1、背景

鸽了很久很久的一个东西了…现在有时间了,还是来把它补齐一下。

双向链表,在 C++ 中经常使用到:

  • [C++系列] 54. list的介绍及使用

习题练手:

  • 146. LRU 缓存

Github 代码仓库,欢迎 start!

  • go-blog list

2、代码实现

双向链表(Doubly Linked List)实现说明

基于 Go 语言实现了一个带有虚拟头结点和虚拟尾结点的双向链表(Doubly Linked List),旨在简化边界条件处理并提高代码可读性与健壮性。

  • 使用虚拟头结点(dummyHead)和虚拟尾结点(dummyTail),避免边界情况下的空指针判断。
  • 所有插入、删除操作均统一处理,无需额外判断是否为头尾节点。
  • 提供正向和反向遍历接口,返回切片便于测试和调试。
  • 插入节点提取公共方法,简化代码。
  • 提供完整的单元测试,保证代码质量。

2.1、v1 版本(未提取公共插入代码)

package v1import ("fmt"
)// ListNode 链表节点数据结构定义
type ListNode struct {prev, next *ListNode // 前驱节点、后继节点val        any       // 数据
}// List 双向链表数据结构定义
type List struct {head, tail *ListNode // 头节点、尾节点len        int       // 链表长度
}// Next ListNode Next 获取下一个节点,如果不存在,则返回nil
func (l *ListNode) Next() *ListNode {if l != nil && l.next != nil {return l.next}return nil
}// Prev ListNode Prev 获取前一个节点,如果不存在,则返回nil
func (l *ListNode) Prev() *ListNode {if l != nil && l.prev != nil {return l.prev}return nil
}// NewList List 创建一个链表
// 使用虚拟结点写法,创建虚拟头结点、尾结点,避免后续各类边界判断
func NewList() *List {dummyHead := &ListNode{val: nil}dummyTail := &ListNode{val: nil}dummyHead.next = dummyTaildummyTail.prev = dummyHeadlist := &List{head: dummyHead,tail: dummyTail,len:  0,}return list
}// PushBack 尾插
func (l *List) PushBack(v any) {node := &ListNode{val: v,}node.next = l.tailnode.prev = l.tail.prevl.tail.prev.next = nodel.tail.prev = nodel.len++
}// PushFront 头插
func (l *List) PushFront(v any) {node := &ListNode{val: v,}node.prev = l.headnode.next = l.head.nextl.head.next.prev = nodel.head.next = nodel.len++
}// InsertAfter 在 at 节点后面插入节点
// at 不存在,则直接插入末尾
func (l *List) InsertAfter(at *ListNode, v any) {if at == nil {l.PushBack(v)return}node := &ListNode{val: v,}node.prev = atnode.next = at.nextnode.prev.next = nodenode.next.prev = nodel.len++
}// InsertBefore 在 at 节点前面插入节点
// at 不存在则直接插入开头
func (l *List) InsertBefore(at *ListNode, v any) {if at == nil {l.PushFront(v)return}node := &ListNode{val: v,}node.next = atnode.prev = at.prevat.prev.next = nodeat.prev = nodel.len++
}// Find 查找节点
// 仅返回第一个匹配的节点
func (l *List) Find(v any) *ListNode {// 跳过虚拟头结点、跳过虚拟尾结点for node := l.head.next; node.Next() != nil; node = node.next {if node.val == v {return node}}return nil
}// Remove 删除节点
func (l *List) Remove(v any) {node := l.Find(v)if node != nil {node.prev.next = node.nextnode.next.prev = node.prevnode.next = nilnode.prev = nill.len--}
}// GetLen 获取长度
func (l *List) GetLen() int {return l.len
}// ForEach 正向遍历
func (l *List) ForEach() []any {res := make([]any, 0)for node := l.head.next; node.Next() != nil; node = node.next {res = append(res, node.val)}return res
}// ForReverse 反向遍历
func (l *List) ForReverse() []any {res := make([]any, 0)for node := l.tail.prev; node.Prev() != nil; node = node.prev {res = append(res, node.val)}return res
}// Print 打印
func (l *List) Print() {res := make([]any, 0)// 跳过虚拟头结点、跳过虚拟尾结点for node := l.head.next; node.Next() != nil; node = node.next {res = append(res, node.val)}fmt.Println(res)
}

2.2、v2 版本(提取公共插入代码)

package v2import ("fmt"
)// ListNode 链表节点数据结构定义
type ListNode struct {prev, next *ListNode // 前驱节点、后继节点val        any       // 数据
}// List 双向链表数据结构定义
type List struct {head, tail *ListNode // 头节点、尾节点len        int       // 链表长度
}// Next ListNode Next 获取下一个节点,如果不存在,则返回nil
func (l *ListNode) Next() *ListNode {if l != nil && l.next != nil {return l.next}return nil
}// Prev ListNode Prev 获取前一个节点,如果不存在,则返回nil
func (l *ListNode) Prev() *ListNode {if l != nil && l.prev != nil {return l.prev}return nil
}// NewList List 创建一个链表
// 使用虚拟结点写法,创建虚拟头结点、尾结点,避免后续各类边界判断
func NewList() *List {dummyHead := &ListNode{val: nil}dummyTail := &ListNode{val: nil}dummyHead.next = dummyTaildummyTail.prev = dummyHeadlist := &List{head: dummyHead,tail: dummyTail,len:  0,}return list
}// insert 插入的通用方法
func (l *List) insert(prev, next *ListNode, v any) {node := &ListNode{val: v, prev: prev, next: next}prev.next = nodenext.prev = nodel.len++
}// PushBack 尾插
func (l *List) PushBack(v any) {l.insert(l.tail.prev, l.tail, v)
}// PushFront 头插
func (l *List) PushFront(v any) {l.insert(l.head, l.head.next, v)
}// InsertAfter 在 at 节点后面插入节点
// at 不存在,则直接插入末尾
func (l *List) InsertAfter(at *ListNode, v any) {if at == nil {l.PushBack(v)return}l.insert(at, at.next, v)
}// InsertBefore 在 at 节点前面插入节点
// at 不存在则直接插入开头
func (l *List) InsertBefore(at *ListNode, v any) {if at == nil {l.PushFront(v)return}l.insert(at.prev, at, v)
}// Find 查找节点
// 仅返回第一个匹配的节点
func (l *List) Find(v any) *ListNode {// 跳过虚拟头结点、跳过虚拟尾结点for node := l.head.next; node != l.tail; node = node.next {if node.val == v {return node}}return nil
}// Remove 删除节点
func (l *List) Remove(v any) {node := l.Find(v)if node != nil {node.prev.next = node.nextnode.next.prev = node.prevnode.next = nilnode.prev = nill.len--}
}// GetLen 获取长度
func (l *List) GetLen() int {return l.len
}// ForEach 正向遍历
func (l *List) ForEach() []any {res := make([]any, 0)for node := l.head.next; node != l.tail; node = node.next {res = append(res, node.val)}return res
}// ForReverse 反向遍历
func (l *List) ForReverse() []any {res := make([]any, 0)for node := l.tail.prev; node != l.head; node = node.prev {res = append(res, node.val)}return res
}// Print 打印
func (l *List) Print() {res := make([]any, 0)// 跳过虚拟头结点、跳过虚拟尾结点for node := l.head.next; node != l.tail; node = node.next {res = append(res, node.val)}fmt.Println(res)
}

3、总结

v2 版本确实是简单易写不易错,且引入了 头尾 的虚拟节点后,在 头插、尾插、头删、尾删 等边界情况下都需要再特殊考虑了。

同时值得一提的是,Go 官方库在一开始其实就支持 list这个数据结构了,且代码写的也十分精简,优雅。

几乎是在 v2 版本上的进一步升级,十分值得学习和使用!

http://www.dtcms.com/wzjs/542578.html

相关文章:

  • 丰台建设企业网站做旅游网站
  • 聊天室网站开发网站设计开发维护
  • 设计感强的网站湖南长沙理工大学
  • 厦门维品网站建设wordpress秀恩爱主题
  • 长沙网络营销学校seo流量排名软件
  • 做网站可以用思源字体吗帮人做网站在徐州被敲诈五万
  • pta编程网站wordpress is_single() 为空
  • 免费推广网站2022北京汽车业务网站开发公司
  • 网站滑动概述网站建设的流程
  • 南昌网站seo哪家公司好建设部网站举报
  • 电子产品网站设计网站硬件方案
  • 宁德北京网站建设做购物网站公司
  • 做彩票网站被免费会员管理软件
  • 网络工程毕设做网站杭州专业网站制作
  • 服装网站建设公司哪家好wordpress默认登录
  • 天猫秘券网站怎么做上海网站建设就q479185700顶上
  • 网站优化推广南宁网站建设推广
  • 网站 面包屑广西建网站哪家好
  • 廊坊设计网站公司启动wordpress linux
  • 做网站复杂吗域名代备案
  • 电子 网站模板网站建设需要注意什么哪些
  • 微博如何做的跟网站一样软件开发外包工作室
  • 网站被提示危险网站中英文网站好处
  • 景县网站建设济南如何挑选网站建设公司
  • 各国网站的域名05网课课练答案
  • 网站自动采集rss经营网站备案查询
  • 做网站需要好多钱广州哪家网站建设服务好
  • 竹子建站教程网站开发毕设论文
  • 建设企业网站价格wordpress 模板开发
  • 博州建设局网站关键词优化公司济南兴田德润团队怎么样