Go实现LinkTable

celeste225800 2022-04-06 10:38:43

数据结构定义

结点:Node

type Node struct {
    prev, next *Node
    linkTable  *LinkTable
    Val        any
}
  • prevnext:用于实现双向链表
  • linkTable:标识结点所属链表
  • Val:结点存储的值

链表:LinkTable

type LinkTable struct {
    head, tail *Node
    len        int
    valType    any
}
  • headtail:标识链表的头尾节点
  • len:当前链表的长度
  • valType:为链表提供泛型支持(go 1.18尚未支持泛型方法)

初始化/销毁LinkTable

Create方法返回一个初始化完的LinkTable

func Create() *LinkTable {
   linkTable := &LinkTable{
      head:    nil,
      tail:    nil,
      len:     0,
      valType: nil,
   }
   return linkTable
}

Clear方法清空LinkTable

func (l *LinkTable) Clear() {
   l.head = nil
   l.tail = nil
   l.len = 0
   l.valType = nil
}

获取LinkTable相关属性

  • GetType:获取链表存储的元素类型
  • Front:获取表头结点
  • Back:获取表尾结点
  • Len:获取链表长度
func (l *LinkTable) GetType() reflect.Type {
   return reflect.TypeOf(l.valType)
}

func (l *LinkTable) Front() *Node {
   return l.head
}

func (l *LinkTable) Back() *Node {
   return l.tail
}

func (l *LinkTable) Len() int {
   return l.len
}

修改链表

  • PushFront:将元素添加至表头
  • PushBack:将元素添加至表头
  • Remove:删除指定结点
func (l *LinkTable) PushFront(v any) *Node {
   n := &Node{
      prev:      nil,
      next:      nil,
      linkTable: l,
      Val:       v,
   }
   if l.head == nil && l.tail == nil {
      l.head = n
      l.tail = n
      l.valType = v
   } else {
      // support generic
      if reflect.TypeOf(v) != reflect.TypeOf(l.valType) {
         return nil
      }
      n.next = l.head
      l.head.prev = n
      l.head = n
   }
   l.len++
   return n
}

func (l *LinkTable) PushBack(v any) *Node {
   n := &Node{
      prev:      nil,
      next:      nil,
      linkTable: l,
      Val:       v,
   }
   if l.head == nil && l.tail == nil {
      l.head = n
      l.tail = n
      l.valType = v
   } else {
      // support generic
      if reflect.TypeOf(v) != reflect.TypeOf(l.valType) {
         return nil
      }
      n.prev = l.tail
      l.tail.next = n
      l.tail = n
   }
   l.len++
   return n
}

func (l *LinkTable) Remove(n *Node) any {
   if n == nil {
      return nil
   }

   if n.linkTable == l {
      switch {
      case l.head == n && l.tail == n:
         l.head = nil
         l.tail = nil
      case l.head == n:
         l.head = l.head.next
         n.next.prev = nil
      case l.tail == n:
         l.tail = l.tail.prev
         n.prev.next = nil
      default:
         n.prev.next = n.next
         n.next.prev = n.prev
      }
      n.prev = nil
      n.next = nil
      n.linkTable = nil
      l.len--
   }
   return n.Val
}

心得

  1. 写个普通链表
  2. struct Node中加Val字段存储值
  3. struct Node中加linkTable字段存储结点所属的链表,用于判断操作的结点是否属于当前链表
  4. struct LinkTable中加入valType字段用来实现简易泛型,在首次向链表插入结点时确定泛型类型
  5. 编写测试文件进行测试,测试案例详见linktable/linktable_test.go

558

https://github.com/merryituxz/linktable

...全文
156 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧