Go组件库总结之介入式链表

本篇文章我们用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)
    }
}
posted @ 2023-02-27 13:36  qxcheng  阅读(17)  评论(0编辑  收藏  举报