Go的数据结构与实现【LinkedList】

[复制链接]
发表于 2026-2-21 09:47:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
先容

所谓链表(Linked List),就是按线性序次分列的一组数据节点。每个节点都是一个对象,它通过一个引用指向对应的数据元素,同时还通过一个引用next指向下一节点。
实现

逻辑方法

我们界说链表的结构体:
  1. // LinkedList the linked list struct
  2. type LinkedList struct {
  3.    sync.RWMutex
  4.    head *Node
  5.    size int
  6. }
  7. // Node a single node that composes the list
  8. type Node struct {
  9.    content T
  10.    next    *Node
  11. }
复制代码
此中包罗头节点和链表长度,在这里我们重要实现以下方法:

  • Add:添加一个元素到链表末端
  • Insert:向链表指定位置插入元素
  • RemoveAt:移除指定索引位置的元素
  • IndexOf:取指定索引位置的元素
  • IsEmpty:判定链表是否为空
  • Size:获取链表长度
  • Traverse:遍历链表并输出
起首是Add方法,判定链表头节点是否为空,若空则设置头节点为插入的元素,若非空,找到链表末端节点,再插入元素。
  1. // Add adds t to the end of the linked list
  2. func (l *LinkedList) Add(t T) {
  3.    l.Lock()
  4.    defer l.Unlock()
  5.    node := NewNode(t)
  6.    if l.head == nil {
  7.       l.head = node
  8.    } else {
  9.       last := l.head
  10.       for {
  11.          if last.next == nil {
  12.             break
  13.          }
  14.          last = last.next
  15.       }
  16.       last.next = node
  17.    }
  18.    l.size++
  19. }
复制代码
Insert方法,注意判定索引位置是否合法,再插入指定位置。
  1. // Insert adds t at position pos
  2. func (l *LinkedList) Insert(t T, pos int) error {
  3.    l.Lock()
  4.    defer l.Unlock()
  5.    // validate position
  6.    if pos < 0 || pos > l.size {
  7.       return fmt.Errorf("insert position must be larger than 0 and smaller than linked list size")
  8.    }
  9.    node := NewNode(t)
  10.    if pos == 0 {
  11.       node.next = l.head
  12.       l.head = node
  13.       return nil
  14.    }
  15.    head := l.head
  16.    idx := 0
  17.    for idx < pos-2 {
  18.       idx++
  19.       head = head.next
  20.    }
  21.    node.next = head.next
  22.    head.next = node
  23.    l.size++
  24.    return nil
  25. }
复制代码
RemoveAt方法与之类似,判定索引位置是否合法再移除。
  1. // RemoveAt removes a node at position pos
  2. func (l *LinkedList) RemoveAt(pos int) (*T, error) {
  3.    l.Lock()
  4.    defer l.Unlock()
  5.    // validate position
  6.    if pos < 0 || pos > l.size {
  7.       return nil, fmt.Errorf("insert position must be larger than 0 and smaller than linked list size")
  8.    }
  9.    head := l.head
  10.    idx := 0
  11.    for idx < pos-1 {
  12.       idx++
  13.       head = head.next
  14.    }
  15.    next := head.next
  16.    head.next = next.next
  17.    l.size--
  18.    return &next.content, nil
  19. }
复制代码
剩下的方法直接取相应数据即可。
  1. // IndexOf returns the position of the t
  2. func (l *LinkedList) IndexOf(t T) int {
  3.    l.RLock()
  4.    defer l.RUnlock()
  5.    head := l.head
  6.    idx := 0
  7.    for {
  8.       if head.content == t {
  9.          return idx
  10.       }
  11.       if head.next == nil {
  12.          return -1
  13.       }
  14.       head = head.next
  15.       idx++
  16.    }
  17. }
  18. // IsEmpty returns true if the list is empty
  19. func (l *LinkedList) IsEmpty() bool {
  20.    l.RLock()
  21.    defer l.RUnlock()
  22.    return l.head == nil
  23. }
  24. // Size returns the linked list size
  25. func (l *LinkedList) Size() int {
  26.    l.RLock()
  27.    defer l.RUnlock()
  28.    return l.size
  29. }
复制代码
遍历方法Traverse还会输出元素内容。
  1. // Traverse traverses linked list
  2. func (l *LinkedList) Traverse() {
  3.    l.RLock()
  4.    defer l.RUnlock()
  5.    head := l.head
  6.    for {
  7.       if head == nil {
  8.          break
  9.       }
  10.       head.Print()
  11.       head = head.next
  12.    }
  13.    fmt.Println()
  14. }
复制代码
单位测试

单位测试如下:
  1. import "testing"
  2. var (
  3.    t1 T = 1
  4.    t2 T = 2
  5.    t3 T = 3
  6.    t4 T = 4
  7. )
  8. func InitLinkedList() *LinkedList {
  9.    list := NewLinkedList()
  10.    list.head = NewNode(t1)
  11.    list.head.next = NewNode(t2)
  12.    list.head.next.next = NewNode(t3)
  13.    list.size = 3
  14.    return list
  15. }
  16. func TestLinkedList_Add(t *testing.T) {
  17.    linkedList := InitLinkedList()
  18.    size := linkedList.Size()
  19.    if size != 3 {
  20.       t.Errorf("linked list size should be 3 but got %d", size)
  21.    }
  22.    linkedList.Add(4)
  23.    size = linkedList.Size()
  24.    if size != 4 {
  25.       t.Errorf("linked list size should be 4 but got %d", size)
  26.    }
  27. }
  28. func TestLinkedList_Insert(t *testing.T) {
  29.    linkedList := InitLinkedList()
  30.    err := linkedList.Insert(t4, 1)
  31.    if err != nil {
  32.       t.Errorf("insert into linked list err %v", err)
  33.    }
  34.    idx1 := linkedList.IndexOf(t2)
  35.    idx2 := linkedList.IndexOf(t4)
  36.    if idx1 != 2 || idx2 != 1 {
  37.       t.Errorf("linked list position is not expected.")
  38.    }
  39. }
  40. func TestLinkedList_RemoveAt(t *testing.T) {
  41.    linkedList := InitLinkedList()
  42.    ret, err := linkedList.RemoveAt(2)
  43.    if err != nil {
  44.       t.Errorf("linked list err %v", err)
  45.    }
  46.    if *ret != t3 {
  47.       t.Errorf("removed item expect 3 but got %d", *ret)
  48.    }
  49.    size := linkedList.Size()
  50.    if size != 2 {
  51.       t.Errorf("linked list size should be 2 but got %d", size)
  52.    }
  53. }
  54. func TestLinkedList_IsEmpty(t *testing.T) {
  55.    linkedList := InitLinkedList()
  56.    empty := linkedList.IsEmpty()
  57.    if empty {
  58.       t.Errorf("linked list is not empty.")
  59.    }
  60.    linkedList = &LinkedList{}
  61.    empty = linkedList.IsEmpty()
  62.    if !empty {
  63.       t.Errorf("linked list is empty.")
  64.    }
  65. }
  66. func TestLinkedList_Traverse(t *testing.T) {
  67.    linkedList := InitLinkedList()
  68.    linkedList.Traverse()
  69. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表