定义一个存储英雄信息的结构HeroNode
,其中next
为下一个英雄节点的内存地址,last
为最后一个英雄节点的内存地址(append时不用遍历)
初始化head
节点,和四个英雄节点
InsertHeroNodeEnd
末尾插入;InsertHeroNodeOrder
比对Tire的大小,找到临界面值
ListHeroNode
输出节点信息(只需要传入head即可)
package main
import (
"fmt"
)
type HeroNode struct {
tier int8 // 英雄所属层级
next *HeroNode //指向下一个节点
last *HeroNode // append操作用
pre *HeroNode //指向前一个节点
name string // 名称
nickname string // 别名
mantra string // 英雄的台词
}
// 2.按照tier 从小到大排序
func InsertHeroNodeOrder(head *HeroNode, newHero *HeroNode) {
currentHeroNode := head
for { // 让插入节点的tier currentHeroNode的下一个节点比较
if currentHeroNode.next == nil { // 符合条件:说明到最后一个节点了还没有匹配到所以最后插入即可
break
} else if currentHeroNode.next.tier >= newHero.tier { // 符合条件说明就刚好插在这个节点后面即可
break
}
currentHeroNode = currentHeroNode.next // 上序条件都不符合,currentHeroNode更新为下一个node的point值
}
newHero.next = currentHeroNode.next // 先让新节点指向后面的节点 (顺序很重要!)
currentHeroNode.next = newHero // 再让当前节点的next指向新节点
}
// 按照英雄名称 将英雄从链表中删除
func DeleteHeroNode(head *HeroNode, name string) {
currentHeroNode := head
flag := false
for {
if currentHeroNode.next == nil {
break
} else if currentHeroNode.next.name == name { // 符合条件表示找到
flag = true
break
}
currentHeroNode = currentHeroNode.next
}
if flag {
currentHeroNode.next = currentHeroNode.next.next
} else {
fmt.Println("没有该英雄...")
}
}
func ListHeroNode(head *HeroNode) { // 循环打印链表信息
currentHeroNode := head
if currentHeroNode.next == nil { // 先判断该链表是不是空链表,符合条件直接退出
fmt.Println("当前链表为空...")
return
}
for { // 从head节点开始。打印下一个节点的信息
fmt.Printf("此节点的前一个point值:%p, 此节点的后一个point值:%p\n", currentHeroNode.pre, currentHeroNode.next)
fmt.Printf("此英雄的point值:%p,Tier:%d,Name:%s,NickName:%s,mantra:%s\n\n",
currentHeroNode.next, currentHeroNode.next.tier, currentHeroNode.next.name,
currentHeroNode.next.nickname, currentHeroNode.next.mantra)
currentHeroNode = currentHeroNode.next // 更新临时变量为当前的指针 (必须在判断前更新)
if currentHeroNode.next == nil {
break
}
}
}
func main() {
head := &HeroNode{}
vayne := &HeroNode{
tier: 3,
name: "vayne",
nickname: "薇恩",
mantra: "让我们来猎杀那些陷入黑暗中的人吧",
}
aphelios := &HeroNode{
tier: 1,
name: "Aphelios",
nickname: "厄斐琉斯",
mantra: "一念一动,天人永隔",
}
verus := &HeroNode{
tier: 1,
name: "verus",
nickname: "维鲁斯",
mantra: "有罪之人必将知道什么叫做痛苦",
}
ezreal := &HeroNode{
tier: 2,
name: "ezreal",
nickname: "探险家",
mantra: " 是时候表演真正的技术了!",
}
// 1.第一种插入方式:在链表的最后加入,
InsertHeroNodeEnd(head, vayne)
InsertHeroNodeEnd(head, aphelios)
InsertHeroNodeEnd(head, ezreal)
InsertHeroNodeEnd(head, verus)
ListHeroNode(head)
// 2.按照tier 从小到大排序
InsertHeroNodeOrder(head, vayne)
InsertHeroNodeOrder(head, aphelios)
InsertHeroNodeOrder(head, ezreal)
InsertHeroNodeOrder(head, verus)
ListHeroNode(head)
}
// 1.第一种插入方式:在链表的最后加入,
func InsertHeroNodeEnd(head *HeroNode, newHero *HeroNode) {
if head.last == nil { //说明除了head节点 没有其他
head.next = newHero
} else {
head.last.next = newHero
newHero.pre = head.last
}
head.last = newHero // 最后在更新下末节点的信息
}
输出(按添加顺序)
此节点的前一个point值:0x0, 此节点的后一个point值:0xc00005c0a0
此英雄的point值:0xc00005c0a0,Tier:3,Name:vayne,NickName:薇恩,mantra:让我们来猎杀那些陷入黑暗中的人吧
此节点的前一个point值:0xc00005c050, 此节点的后一个point值:0xc00005c0f0
此英雄的point值:0xc00005c0f0,Tier:1,Name:Aphelios,NickName:厄斐琉斯,mantra:一念一动,天人永隔
此节点的前一个point值:0xc00005c0a0, 此节点的后一个point值:0xc00005c190
此英雄的point值:0xc00005c190,Tier:2,Name:ezreal,NickName:探险家,mantra: 是时候表演真正的技术了!
此节点的前一个point值:0xc00005c0f0, 此节点的后一个point值:0xc00005c140
此英雄的point值:0xc00005c140,Tier:1,Name:verus,NickName:维鲁斯,mantra:有罪之人必将知道什么叫做痛苦
基本与末尾插入一样,只需要在
insert
的时候判断下Tier大小,从而确定插入位置
// 2.按照tier 从小到大排序。(这里的指向更改优点麻烦,最好画图理解下。有好方法在补充。)
func InsertHeroNodeOrder(head *HeroNode, newHero *HeroNode) {
currentHeroNode := head
for { // 让插入节点的tier currentHeroNode的下一个节点比较
if currentHeroNode.next == nil { // 符合条件:说明到最后一个节点了还没有匹配到所以最后插入即可
currentHeroNode.next = newHero
newHero.pre = currentHeroNode
break
} else if currentHeroNode.next.tier >= newHero.tier { // 符合条件说明就刚好插在这个节点后面即可
newHero.next = currentHeroNode.next
newHero.pre = currentHeroNode // 先让新节点与前后节点联系
currentHeroNode.next.pre = newHero // 一定要先建立当前节点的下一个节点与新节点的关系
currentHeroNode.next = newHero
break
}
currentHeroNode = currentHeroNode.next // 上序条件都不符合,currentHeroNode更新为下一个node的point值
}
}
输出(按Tier顺序)
此节点的前一个point值:0x0, 此节点的后一个point值:0xc00005c140
此英雄的point值:0xc00005c140,Tier:1,Name:verus,NickName:维鲁斯,mantra:有罪之人必将知道什么叫做痛苦
此节点的前一个point值:0xc00005c050, 此节点的后一个point值:0xc00005c0f0
此英雄的point值:0xc00005c0f0,Tier:1,Name:Aphelios,NickName:厄斐琉斯,mantra:一念一动,天人永隔
此节点的前一个point值:0xc00005c140, 此节点的后一个point值:0xc00005c190
此英雄的point值:0xc00005c190,Tier:2,Name:ezreal,NickName:探险家,mantra: 是时候表演真正的技术了!
此节点的前一个point值:0xc00005c0f0, 此节点的后一个point值:0xc00005c0a0
此英雄的point值:0xc00005c0a0,Tier:3,Name:vayne,NickName:薇恩,mantra:让我们来猎杀那些陷入黑暗中的人吧
// 按照英雄名称 将英雄从链表中删除
func DeleteHeroNode(head *HeroNode, name string) {
currentHeroNode := head
flag := false
for {
if currentHeroNode.next == nil {
break
} else if currentHeroNode.next.name == name { // 符合条件表示找到
flag = true
break
}
currentHeroNode = currentHeroNode.next
}
if flag {
if currentHeroNode.next.next == nil { //说明要删除的节点就是末节点
currentHeroNode.next = nil
} else {
currentHeroNode.next.next.pre = currentHeroNode
currentHeroNode.next = currentHeroNode.next.next
}
} else {
fmt.Println("没有该英雄...")
}
}
改查逻辑类似
原文:https://www.cnblogs.com/3rdworld/p/13126266.html