Go实现双链表

双向链表

  List 是一个相当简单的结构体,其中只包含了一个root的节点和一个整型的len。一个List代表一条链表,而len就是该链表的元素个数

// Element 创建双链表的节点
type Element struct {
	next, prev *Element
	Value      any
	list       *DList
}
type DList struct {
	Length uint
	root   Element
}

  root是一个虚拟节点(哨兵仅当做标记来使用),即root这个节点不包含在链表元素内,它仅仅是用来记录链表的头和尾的一个辅助节点,加上了虚拟节点的链表如下图所示:

在这里插入图片描述

插入演示

  第一步,e.prev = root.Prev。先把新插入的元素的Prev指针,指向最后一个元素的指针
在这里插入图片描述

  第二步,把新元素的Next指向root节点,也就是。e…next = root.prev.next

在这里插入图片描述
  第三步,把最后一个元素的next指向新元素,e.prev.next = e

在这里插入图片描述
  第四步,把root节点的prev指向新元素,root.prev = e 或者 e.next.prev = e
在这里插入图片描述

前插后插代码

// Element 创建双链表的节点
type Element struct {
	next, prev *Element
	Value      any
	list       *DList
}
type DList struct {
	Length uint
	root   Element
}

func NewDList() *DList {
	return new(DList).Init()
}
func (l *DList) Init() *DList {
	l.root.next = &l.root
	l.root.prev = &l.root
	l.Length = 0
	return l
}
func (l *DList) insert(e, root *Element) {
	// root 为per的地址,刚开始一直都是初始化的地址,我们要把最后一个的pre的地址加入到,新插入的pre中
	e.prev = root
	// 把刚开始的初始化的节点传给新节点
	e.next = root.next
	e.prev.next = e
	e.next.prev = e
	e.list = l
	l.Length++
}

// PushBack 后插
func (l *DList) PushBack(v any) {
	l.insert(&Element{Value: v}, l.root.prev)
}

// FrontBack 前插
func (l *DList) FrontBack(v any) {
	l.insert(&Element{Value: v}, &l.root)
}

返回代码的第一和最后一个元素

直接通过root就可以看首位节点

// Front 返回双链表的第一个元素地址
func (l *DList) Front() *Element {
	if l.Length == 0 {
		return nil
	}
	return l.root.next
}

// Back 返回双链表的做后一个元素地址
func (l *DList) Back() *Element {
	if l.Length == 0 {
		return nil
	}
	return l.root.prev
}

打印和删除操作

删除元素是删除所有的相同的value

// PrintlnDList 打印双链表的所有元素
func (l *DList) PrintlnDList() {
	if l.Length == 0 {
		log.Infof("双链表中没有元素")
	}
	prev := l.root.next
	index := 0
	for prev.Value != nil {
		fmt.Printf("下标index: %d 元素 Element: %s\n", index, prev.Value)
		prev = prev.next
		index++
	}
	return
}

// RemoveElement 根据元素删除
func (l *DList) RemoveElement(v any) bool {
	prev := l.root.next
	count := 0
	index := 0
	for prev.Value != nil {
		if prev.Value == v {
			prev.prev.next = prev.next
			prev.next.prev = prev.prev
			l.Length--
			count++
			fmt.Printf("删除的元素Info 下标index: %d 元素 Element: %s\n", index, prev.Value)
		}
		prev = prev.next
		index++
	}
	if count == 0 {
		fmt.Println("链表中没有该元素")
	}
	return true
}

全部代码

package main

import (
	"fmt"
	"github.com/google/martian/log"
)

// Element 创建双链表的节点
type Element struct {
	next, prev *Element
	Value      any
	list       *DList
}
type DList struct {
	Length uint
	root   Element
}

func NewDList() *DList {
	return new(DList).Init()
}
func (l *DList) Init() *DList {
	l.root.next = &l.root
	l.root.prev = &l.root
	l.Length = 0
	return l
}
func (l *DList) insert(e, root *Element) {
	// root 为per的地址,刚开始一直都是初始化的地址,我们要把最后一个的pre的地址加入到,新插入的pre中
	e.prev = root
	// 把刚开始的初始化的节点传给新节点
	e.next = root.next
	e.prev.next = e
	e.next.prev = e
	e.list = l
	l.Length++
}

// PushBack 后插
func (l *DList) PushBack(v any) {
	l.insert(&Element{Value: v}, l.root.prev)
}

// FrontBack 前插
func (l *DList) FrontBack(v any) {
	l.insert(&Element{Value: v}, &l.root)
}

// Front 返回双链表的第一个元素地址
func (l *DList) Front() *Element {
	if l.Length == 0 {
		return nil
	}
	return l.root.next
}

// Back 返回双链表的做后一个元素地址
func (l *DList) Back() *Element {
	if l.Length == 0 {
		return nil
	}
	return l.root.prev
}

// PrintlnDList 打印双链表的所有元素
func (l *DList) PrintlnDList() {
	if l.Length == 0 {
		log.Infof("双链表中没有元素")
	}
	prev := l.root.next
	index := 0
	for prev.Value != nil {
		fmt.Printf("下标index: %d 元素 Element: %s\n", index, prev.Value)
		prev = prev.next
		index++
	}
	return
}

// RemoveElement 根据元素删除
func (l *DList) RemoveElement(v any) bool {
	prev := l.root.next
	count := 0
	index := 0
	for prev.Value != nil {
		if prev.Value == v {
			prev.prev.next = prev.next
			prev.next.prev = prev.prev
			l.Length--
			count++
			fmt.Printf("删除的元素Info 下标index: %d 元素 Element: %s\n", index, prev.Value)
		}
		prev = prev.next
		index++
	}
	if count == 0 {
		fmt.Println("链表中没有该元素")
	}
	return true
}
func main() {
	ab := NewDList()
	ab.PushBack("sdfd")
	ab.PushBack("sd")
	ab.PushBack("sad")
	ab.PushBack("sdfd")
	ab.PushBack("sdfd")
	ab.PushBack("sdfd")
	ab.PrintlnDList()
	ab.RemoveElement("sdfd")
	ab.PushBack("sdfd")
	ab.PrintlnDList()
}
  • 21
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Go 的学习之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值