双向链表

双向链表

结点数据结构
type LinkNode struct {
    Data interface{}
    Prev *LinkNode
    Next *LinkNode
}

在这里插入图片描述

双向链表方法:
1. 创建链表 Create(数据)
2. 打印链表 Print()
3. 获取结点个数 Length() int
4. 插入结点 Insert(index, 数据)
5. 删除结点 Delete(index)
6. 销毁链表 Destroy()

go实现

创建双向链表:

1. 容错
2. 创建头结点 head = node
3. 遍历 Data 参数列表,依次创建新结点。 初始化
   1. newNode.Prev = node
   2. node.Next = newNode
   3. node = node.Next
4. 还原头结点
// 创建双向链表结点
type LinkNode struct {
	Data interface{} // 数据域
	Prev *LinkNode   // 前引指针域
	Next *LinkNode   // 后继指针域
}

// 创建双向链表
func (node *LinkNode) Create(Data ...interface{}) {
	if node == nil || Data == nil {
		return
	}
	if len(Data) == 0 {
		return
	}
	// 创建头结点
	head := node

	// 循环Data 创建数据结点
	for _, v := range Data {
		// 创建新结点,并初始化
		newNode := new(LinkNode)
		newNode.Data = v
		newNode.Prev = node
		newNode.Next = nil

		node.Next = newNode		// 当前结点的下一个结点 赋值为新结点
		node = node.Next		// 更新新结点为当前结点
	}
	// 还原头结点
	node = head
}

正序打印 – 递归:

1. 容错,递归出口
2. 判断 node.Data 不为空,打印数据
3. 递归调用 本函数。 

// 双向链表打印 --- 递归 --正向
func (node *LinkNode) Print1() {
	if node == nil { // 容错,递归出口
		return
	}
	if node.Data != nil {
		fmt.Print(node.Data, " ")
	}
	// 递归调用本函数
	node.Next.Print1()
}

倒序打印 – 循环:

1. 容错
2. 找到链表尾结点,保存在 node 中
3. 循环,从链表的尾结点开始,使用 prev ,依次向前打印
   1. 判断 node.Data 不为空,打印数据
// 双向链表打印 --- 循环 --反向
func (node *LinkNode) Print2() {
	if node == nil { // 容错
		return
	}
	// 找到链表的尾结点,保存在 node 中
	for node.Next != nil {
		node = node.Next
	}

	// 借助 prev 倒序 打印链表数据
	for node.Prev != nil {
		// 打印数据
		if node.Data != nil {
			fmt.Print(node.Data, " ")
		}
		// node依次前移
		node = node.Prev
	}
}

按位置插入结点:

1. 容错
2. 定义 preNode 用来保存 index 对应的前一个结点
3. 循环 移动 node、preNode。 循环结束时, node 保存 index 对应结点。
4. 创建新结点, 初始化
   1. 数据域初始化
   2. 新结点的 Prev, 是  preNode
   3. 新结点的 Next,是 node
5. node 的Prev 指向 新结点
6. preNode 的 Next 指向 新结点。

在这里插入图片描述

// 按位置插入链表结点
func (node *LinkNode) InsertByIndex(index int, Data interface{}) {
	if node == nil || Data == nil {
		return
	}
	if index < 0 || index > node.Length() {
		return
	}
	// 定义preNode ,保存前一个结点
	preNode := node

	// 循环 找到 index 对应结点, 保存在 node 中
	for i := 0; i < index; i++ {
		preNode = node
		node = node.Next
	}	// 循环结束, node指向index 对应结点, prenode 指向前一个结点

	// 创建新结点
	newNode := new(LinkNode)
	newNode.Data = Data
	newNode.Prev = preNode
	newNode.Next = node

	// node 的 prev指向新结点
	node.Prev = newNode

	// preNode 的 next 是新结点
	preNode.Next = newNode
}

按位置删除结点:

1. 容错
2. 定义preNode , 用来保存 index 对应的前一个结点
3. 循环找到 node 、preNode
4. 将 preNode 的 Next 指向 node 的 Next
5. 将 node 的 下一个结点的 Prev 保存 preNode
6. 置空 摘下的结点,促使GC工作
7. 判断 如果 index 为 链表的 尾结点时
   1. 将 尾结点(node)的 前一个结点 (preNode)的Next 置空
   2. 将 尾结点 置空 。  促使GC工作

在这里插入图片描述

/ 按位置删除链表结点
func (node *LinkNode) DeleteByIndex(index int) {
	if node == nil  {
		return
	}
	if index < 0 || index > node.Length() {
		return
	}

	l := node.Length()	// 保存长度,防止后续node变化,无法获取链表完整长度。

	// 定义 preNode 记录 index 对应的前一个结点
	preNode := node

	// 循环 移动 preNode 和 node
	for i:=0; i<index; i++ {
		preNode = node
		node = node.Next
	}

	// 如果 index 是最后一个结点
	if index == l{
		preNode.Next = nil

		node.Data = nil
		node.Prev = nil
		node.Next = nil
		node = nil
		return
	} else {
		// 将 preNode 的 next 保存 node 的 下一个结点
		preNode.Next = node.Next

		// 将 node 的一下结点 的 prev 保存 preNode
		node.Next.Prev = preNode

		// 置空摘下的结点
		node.Data = nil
		node.Prev = nil
		node.Next = nil
		node = nil
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值