楔子
go 学习
demo
package main
import (
"fmt"
)
//双链表|
type HeroNode struct {
no int
name string
nickname string
next *HeroNode //下一个英雄
pre *HeroNode
}
func (h *HeroNode) String() string {
return fmt.Sprintf("[%d %s %s]==>", h.no, h.name, h.nickname)
}
func InsertHeroNode(head *HeroNode, newHeroNode *HeroNode) {
//思路
//1. 先找到该链表的最后这个结点
temp := head
for {
if temp.next == nil { //表示找到最后
break
}
temp = temp.next // 让temp不断的指向下一个结点
}
//3. 将newHeroNode加入到链表的最后
temp.next = newHeroNode
newHeroNode.pre = temp
}
//显示链表的所有结点信息
func ListHeroNode(head *HeroNode) {
//1. 创建一个辅助结点[跑龙套, 帮忙]
temp := head
// 先判断该链表是不是一个空的链表
if temp.next == nil {
fmt.Println("空空如也。。。。")
return
}
//2. 遍历这个链表
for {
fmt.Printf("[%d , %s , %s]==>", temp.next.no,
temp.next.name, temp.next.nickname)
//判断是否链表后
temp = temp.next
if temp.next == nil {
break
}
}
}
func ListHeroNode_my(head *HeroNode) {
fmt.Println()
//1 创建临时结点
temp := head
//选判断该链表是不是空链表
for {
if temp.next == nil {
break
}
temp = temp.next
fmt.Print(temp)
}
}
func main() {
//一个头结点
head := &HeroNode{}
// 创建一个新的 heronode
hero1 := &HeroNode{
no: 1,
name: "宋江",
nickname: "及时雨",
}
hero2 := &HeroNode{
no: 2,
name: "卢俊义",
nickname: "玉麒麟",
}
hero3 := &HeroNode{ no: 3, name: "林冲", nickname: "豹子头", }
hero5 := &HeroNode{no: 5, name: "关胜", nickname: "大刀",}
hero7 := &HeroNode{no: 7, name: "林冲", nickname: "豹子头",}
hero6 := &HeroNode{no: 6, name: "林冲A", nickname: "豹子头A",}
InsertHeroNode2(head, hero7)
InsertHeroNode2(head, hero5)
InsertHeroNode2(head, hero6)
InsertHeroNode2(head, hero2)
InsertHeroNode2(head, hero3)
InsertHeroNode2(head, hero1)
ListHeroNode_my(head)
DelHernNode(head, 3)
ListHeroNode_my(head)
}
func DelHernNode(head *HeroNode, delId int) {
temp := head
//TODO 找到要删除的节点
flag := false
for {
if temp.next == nil { //插入到最后
break
} else if temp.next.no == delId { //此位置调整之后即可为从大到小
//找到删除的节点
flag = true
break
}
temp = temp.next
}
if flag {
if temp.next.next == nil { //该节点就是最后一个节点
temp.next = nil
} else {
temp = temp.next
temp.pre.next = temp.next
temp.next.pre = temp.pre
}
}
}
//韩顺平 方法
func InsertHeroNode2(head *HeroNode, newHeroNode *HeroNode) {
//思路
//1. 先找到该链表的最后这个结点
//2. 创建一个辅助结点[跑龙套, 帮忙]
temp := head
//flag := true
// 让插入的节点no 和temp的下一个节点no比较
for ; ; {
if temp.next == nil { //插入到最后
break
} else if temp.next.no >= newHeroNode.no { //此位置调整之后即可为从大到小
//应该插入temp
break
} else if temp.next.no == newHeroNode.no {
break
}
temp = temp.next
}
newHeroNode.next = temp.next
newHeroNode.pre = temp
if temp.next != nil {
temp.next.pre = newHeroNode
}
//别忘了该节点
temp.next = newHeroNode
}
约瑟夫
package main
import "fmt"
//编写一个函数,构成单向的环形链表|
type Boy struct {
No int
Next *Boy //指向下一个小孩的指针
}
func (b *Boy) String() string {
return fmt.Sprintf("[%d ]=>", b.No)
}
// num 小孩个数,
//返回第一个小孩指针
func AddBoy(num int) *Boy {
first := &Boy{}
curBoy := &Boy{}
if num < 1 {
fmt.Println("num值不对")
return first
}
//构建环形链表
for i := 1; i <= num; i++ {
boy := &Boy{
No: i,
}
//1 第一个小孩,|构成循环链表需要一个辅助指针
if i == 1 {
first = boy
curBoy = boy
curBoy.Next = boy
} else {
curBoy.Next = boy
curBoy = boy
curBoy.Next = first //构成环形链表
}
}
return first
}
//显示单向环形链表
func showBoy(first *Boy) {
//如果为空
if first.Next == nil {
fmt.Println("链表为空~")
return
}
temp := first //说明至少有1个小孩
for ; ; {
fmt.Print(temp)
if temp.Next == first {
break
}
temp = temp.Next
}
}
//上面两个方法是环形链表的构建显示
func main() {
boy := AddBoy(5)
showBoy(boy)
fmt.Println()
PlayGame(boy,2,3)
}
//编号从1 ...n的人围坐一圈,约定编号为k (1<=k<=n)
func PlayGame(first *Boy, startNo int, coutNum int) {
//1 空链表,单独处理
if first.Next == nil {
fmt.Println("空的链表,没有小孩")
return
}
// startNo要小于小孩的总数
// 删除小孩
tail := first //tail执行环形链表的最后一个小孩,
for {
if tail.Next == first {
break
}
tail = tail.Next
}
for i := 1; i <= startNo-1; i++ {
first = first.Next
tail = tail.Next
}
// 开始数countNum,删除first指向的小孩
for {
for i := 1; i <= coutNum-1; i++ {
first = first.Next
tail = tail.Next
}
//删除first的节点
fmt.Println("出列的是", first)
first = first.Next
tail.Next = first
if tail == first {
break
}
}
fmt.Println("最后的小孩是", first)
}