链表

单链表

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

type Value int

type Node struct {
    Data Value
    Next *Node
}

//查找前驱节点
func FindPrevious(data Value, h *Node) *Node {
    t := h
    for t.Next != nil && t.Next.Data != data {
        t = t.Next
    }
    return t
}

//p节点插入data
func Insert(data Value, p *Node) {
    tmpNode := &Node{Data: data}
    tmpNode.Next = p.Next
    p.Next = tmpNode
}

func Delete(data Value, h *Node) {
    p := FindPrevious(data, h)
    if p.Next.Next == nil {
        p.Next = nil
    } else {
        tmp := p.Next
        p.Next = tmp.Next
        tmp.Next = nil
    }
}

func Find(data Value, h *Node) *Node {
    t := h
    for t.Data != data {
        t = t.Next
    }
    return t
}

//找中点
func FindMiddle(h *Node) *Node {
    if h.Next == nil {
        return h
    }
    if h.Next.Next == nil {
        return h
    }
    t, t2 := h, h.Next.Next
    for t2.Next != nil && t2.Next.Next != nil {
        t = t.Next
        t2 = t2.Next.Next
    }
    return t.Next
}

//翻转
func Reverse(h *Node) *Node {
    t := &Node{}
    for h != nil {
        tmp := h
        h = h.Next
        tmp.Next = t.Next
        t.Next = tmp
    }
    ret := t.Next
    t.Next = nil
    return ret 
}

//检测是否有环
func CheckExistLoop(h *Node) bool {
    if h == nil {
        return false
    }
    if h.Next == nil {
        return false
    }
    t, t2 := h, h.Next.Next
    for t2.Next != nil && t2.Next.Next != nil {
        t = t.Next
        t2 = t2.Next.Next
        if t == t2 {
            return true
        }
    }
    return false
}

//找到环入口节点
func GetLoopHead(h *Node) *Node {
    if h == nil {
        return nil
    }
    if h.Next == nil {
        return nil
    }
    t, t2 := h, h.Next.Next
    for t2.Next != nil && t2.Next.Next != nil {
        t = t.Next
        t2 = t2.Next.Next
        if t == t2 {
            break
        }
    }
    if t != t2 {
        return nil
    }
    t2 = h.Next
    for t2 != t {
        t2 = t2.Next
        t = t.Next
    }
    return t
}

//找倒数第k个节点
func GetTailK(h *Node, k int) *Node {
    if h == nil {
        return nil
    }
    c := 0
    t := h
    for c < k && t != nil {
        c++
        t = t.Next
    }
    if t == nil {
        return t
    }
    t2 := h
    for t != nil {
        t = t.Next
        t2 = t2.Next
    }
    return t2
}

双向链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

container/list包实现了基本的双向链表(双向循环链表)功能,包括元素的插入、删除、移动功能

package list
//结构体
//双向链表中的元素抽象
type Element struct {
    next, prev *Element
    //该元素属于哪个list,相当于链表的头指针
    list *List
    //具体记录数据
    Value interface{}
}

//返回后继元素
func (e *Element) Next() *Element {
    //只有list的root会存在next等于自己
    if p := e.next; e.list != nil && p != &e.list.root {
        return p
    }
    return nil
}

//返回前驱元素
func (e *Element) Prev() *Element {
    //只有list的root会存在prev等于自己
    if p := e.prev; e.list != nil && p != &e.list.root {
        return p
    }
    return nil
}

//双向链表List的定义
type List struct {
    //list的头结点,是没有值的,见Init函数的构建过程
    root Element 
    //定义长度
    len  int     
}
func (l *List) Init() *List {
    l.root.next = &l.root
    l.root.prev = &l.root
    l.len = 0
    return l
}
//初始化
func New() *List { return new(List).Init() }
//返回list的长度
func (l *List) Len() int { return l.len }
//返回list的下一个元素
func (l *List) Front() *Element {
    if l.len == 0 {
        return nil
    }
    return l.root.next
}
//返回list的上一个元素
func (l *List) Back() *Element {
    if l.len == 0 {
        return nil
    }
    return l.root.prev
}
//懒加载
func (l *List) lazyInit() {
    if l.root.next == nil {
        l.Init()
    }
}
//at元素后面加一个元素e
//经典双向链表的插入,只是e需要把list指向当前list
func (l *List) insert(e, at *Element) *Element {
    n := at.next
    at.next = e
    e.prev = at
    e.next = n
    n.prev = e
    e.list = l
    l.len++
    return e
}

func (l *List) insertValue(v interface{}, at *Element) *Element {
    return l.insert(&Element{Value: v}, at)
}
//移除元素e
//经典的双链表删除元素
func (l *List) remove(e *Element) *Element {
    e.prev.next = e.next
    e.next.prev = e.prev
    e.next = nil //避免内存泄漏
    e.prev = nil 
    e.list = nil
    l.len--
    return e
}
//移除list的元素e
func (l *List) Remove(e *Element) interface{} {
    if e.list == l {
        l.remove(e)
    }
    return e.Value
}
//list的头部插入值为v的元素
func (l *List) PushFront(v interface{}) *Element {
    l.lazyInit()
    return l.insertValue(v, &l.root)
}
//list的末尾插入值为v的元素
func (l *List) PushBack(v interface{}) *Element {
    l.lazyInit()
    return l.insertValue(v, l.root.prev)
}
//mark前面插入值为v的节点
func (l *List) InsertBefore(v interface{}, mark *Element) *Element {
    if mark.list != l {
        return nil
    }
    return l.insertValue(v, mark.prev)
}
//mark后门插入值为v的节点
func (l *List) InsertAfter(v interface{}, mark *Element) *Element {
    if mark.list != l {
        return nil
    }
    return l.insertValue(v, mark)
}
//将节点e移动到root的后门,可视为前置
func (l *List) MoveToFront(e *Element) {
    //e的list不是l或者e已经是单节点了
    if e.list != l || l.root.next == e {
        return
    }
    //打一套组合拳
    //先删除然后移动到root的后门
    l.insert(l.remove(e), &l.root)
}
//将节点e移动到root的前面,可视为后置
func (l *List) MoveToBack(e *Element) {
    if e.list != l || l.root.prev == e {
        return
    }
    l.insert(l.remove(e), l.root.prev)
}

func (l *List) MoveBefore(e, mark *Element) {
    if e.list != l || e == mark || mark.list != l {
        return
    }
    l.insert(l.remove(e), mark.prev)
}

func (l *List) MoveAfter(e, mark *Element) {
    if e.list != l || e == mark || mark.list != l {
        return
    }
    l.insert(l.remove(e), mark)
}
//合并其他list到l的最后
func (l *List) PushBackList(other *List) {
    l.lazyInit()
    for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
        l.insertValue(e.Value, l.root.prev)
    }
}
//合并其他list到l的前面
func (l *List) PushFrontList(other *List) {
    l.lazyInit()
    for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
        l.insertValue(e.Value, &l.root)
    }
}

原文链接: https://www.cnblogs.com/weiweng/p/12486364.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    链表

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/373102

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月3日 上午11:35
下一篇 2023年3月3日 上午11:35

相关推荐