动手写个网络协议栈吧2.1 一个侵入式链表的实现

链表以及golang介入式链表的实现

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
简单的说链表是一个具有逻辑顺序的线性表,每一个节点里存到下一个节点的指针。

链表有啥用?

因为链表插入很快,而且具有动态性,想添加几个元素就添加几个(内存空间足够),不像数组一样那么死板,正因为链表的灵活性,所有链表的用处是大大的有啊。
链表最适合用于频繁更新变化的数据,比如一个需要异步执行并且不可丢失的命令序列、一个需要进行实时加载与卸载的驱动,无序且数量未知,这个时候就需要链表结构来协助完成数据的管理。如果不需要过度关注数据的顺序,还可以用链表方便快捷地在任意一个地方插入或删除一个元素,并且不会影响到其它的元素。

介入式链表(intrusive list)

前面的链表都是普通链表,记得<<c语言程序设计>>上讲的链表也是一样,就是链表的节点指针和数据段是放在同一个struct,每实现一个不同的struct就得重新实现一遍链表的功能,这对于“懒惰”的程序员来说是不可忍受的,所以就出来了介入式链表,将数据段和链表的功能区别开来。

package main

import (
        "fmt"
)

type Intrusive interface {
        Next() Intrusive
        Prev() Intrusive
        AddNext(Intrusive)
        AddPrev(Intrusive)
}

type List struct {
        prev Intrusive
        next Intrusive
}

func (l *List) Next() Intrusive {
        return l.next
}

func (l *List) Prev() Intrusive {
        return l.prev
}

func (l *List) AddNext(i Intrusive) {
        l.next = i
}

func (l *List) AddPrev(i Intrusive) {
        l.prev = i
}

func (l *List) Front() Intrusive {
        return l.prev
}

func (l *List) Back() Intrusive {
        return l.next
}

func (l *List) PushFront(e Intrusive) {
        e.AddPrev(nil)
        e.AddNext(l.prev) // 指向第一个节点

        if l.prev != nil {
                l.prev.AddPrev(e)
        } else {
                l.next = e
        }
        l.prev = e

}

func (l *List) PushBack(e Intrusive) {
        e.AddPrev(l.next) // 指向最后一个节点
        e.AddNext(nil)

        if l.next != nil {
                l.next.AddNext(e)
        } else {
                l.prev = e
        }

        l.next = e

}

// InsertAfter inserts e after b.
func (l *List) InsertAfter(e, b Intrusive) {
        a := b.Next()
        e.AddNext(a)
        e.AddPrev(b)
        b.AddNext(e)

        if a != nil {
                a.AddPrev(e)
        } else {
                l.next = e
        }
}

// InsertBefore inserts e before a.
func (l *List) InsertBefore(e, a Intrusive) {
        b := a.Prev()
        e.AddNext(a)
        e.AddPrev(b)
        a.AddPrev(e)

        if b != nil {
                b.AddNext(e)
        } else {
                l.prev = e
        }
}

// Remove removes e from l.
func (l *List) Remove(e Intrusive) {
        prev := e.Prev()
        next := e.Next()

        if prev != nil {
                prev.AddNext(next)
        } else {
                l.prev = next
        }

        if next != nil {
                next.AddPrev(prev)
        } else {
                l.next = prev
        }
}

func main() {
        type E struct {
                List
                data int
        }
        // Create a new list and put some numbers in it.
        l := List{}
        e4 := &E{data: 4}
        e3 := &E{data: 3}
        e2 := &E{data: 2}
        e1 := &E{data: 1}

        l.PushFront(e4)
        l.PushFront(e3)
        l.PushFront(e2)
        l.PushFront(e1)

        fmt.Println()

        for e := l.Front(); e != nil; e = e.Next() {
                fmt.Printf("e: %+v\n", e)
                fmt.Printf("data: %d\n", e.(*E).data)
        }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值