go实现单链表



  1. 定义一个存储英雄信息的结构HeroNode,其中next为下一个英雄节点的内存地址,last为最后一个英雄节点的内存地址(append时不用遍历)
  2. 初始化head节点,和四个英雄节点
  3. InsertHeroNodeEnd 末尾插入;InsertHeroNodeOrder比对Tire的大小,找到临界面值
  4. 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)
 }



// 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:有罪之人必将知道什么叫做痛苦



基本与末尾插入一样,只需要在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:让我们来猎杀那些陷入黑暗中的人吧



// 按照英雄名称 将英雄从链表中删除
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("没有该英雄...")
	}
}

改查逻辑类似