链表学习-单链表go实现 [2]
go实现单链表
示例代码
-
定义一个存储英雄信息的结构
HeroNode
,其中next
为下一个英雄节点的内存地址,last
为最后一个英雄节点的内存地址(append时不用遍历) -
初始化
head
节点,和四个英雄节点 -
InsertHeroNodeEnd
末尾插入;InsertHeroNodeOrder
比对Tire的大小,找到临界面值 -
ListHeroNode
输出节点信息(只需要传入head即可)
package main
import "fmt"
type HeroNode struct {
tier int8 // 英雄所属层级
next *HeroNode //指向下一个节点
last *HeroNode // append操作用
name string // 名称
nickname string // 别名
mantra string // 英雄的台词
}
func ListHeroNode(head *HeroNode) {// 循环打印链表信息
currentHeroNode := head
if currentHeroNode.next == nil {// 先判断该链表是不是空链表,符合条件直接退出
fmt.Println("当前链表为空...")
return
}
for {// 从head节点开始。打印下一个节点的信息
fmt.Printf("↓ Tier:%d,Name:%s,NickName:%s,mantra:%s\n\n",
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)
}
go单链表末尾节点
// 1.第一种插入方式:在链表的最后加入,
func InsertHeroNodeEnd(head *HeroNode, newHero *HeroNode) {
if head.last == nil { //表示除头结点外 没有其他节点
head.next = newHero
} else {
head.last.next = newHero
}
head.last = newHero // 记录最后一个节点信息
}
输出(按添加顺序)
↓ Tier:3,Name:vayne,NickName:薇恩,mantra:让我们来猎杀那些陷入黑暗中的人吧
↓ Tier:1,Name:Aphelios,NickName:厄斐琉斯,mantra:一念一动,天人永隔
↓ Tier:2,Name:ezreal,NickName:探险家,mantra: 是时候表演真正的技术了!
↓ Tier:1,Name:verus,NickName:维鲁斯,mantra:有罪之人必将知道什么叫做痛苦
go实现单链表按Hero Tier顺序插入
基本与末尾插入一样,只需要在
insert
的时候判断下Tier大小,从而确定插入位置
// 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指向新节点
}
输出(按Tier顺序)
↓ Tier:1,Name:verus,NickName:维鲁斯,mantra:有罪之人必将知道什么叫做痛苦
↓ Tier:1,Name:Aphelios,NickName:厄斐琉斯,mantra:一念一动,天人永隔
↓ Tier:2,Name:ezreal,NickName:探险家,mantra: 是时候表演真正的技术了!
↓ Tier:3,Name:vayne,NickName:薇恩,mantra:让我们来猎杀那些陷入黑暗中的人吧
go实现链表删除
// 按照英雄名称 将英雄从链表中删除
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("没有该英雄...")
}
}
改查逻辑类似