双向链表
结点数据结构
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
}
}