前段时间忙,一直没有更新。疫情期间,只能闭关在家,继续研究go,编写了不少算法,慢慢上传更新吧😂,也算给我未来的儿子留点笔记😂😄。
用Go编写一个环形单链表,解决Joseph的问题。要求如下:
设编号为1,2....n的n个人围坐一圈,约定的编号为k(1 <=k <=n) 的人,从1开始报数,数到m(1<=m<=n)的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
代码部分:
package main
import (
"fmt"
"os"
)
//定义一个结构体
type Children struct {
No int
Next *Children //默认值为nil
}
//构建单向环形链表
//num: 要构建的环形链表的小孩的数量
//*Children 返回一个头指针
func AddChild(num int) *Children {
first := &Children{} //空节点
curChild := &Children{} //辅助指针
if num < 1 {
fmt.Println("wrong num")
return nil
}
//循环的构建
for i := 1; i <= num; i++ {
child := &Children{
No: i,
}
//第一个小孩比较特殊
if i == 1 { //第一个小孩
first = child //将first指针指向第一个节点
curChild = child
curChild.Next = first //构成圆环 (如果只有一个节点,则自己指向自己)
} else {
curChild.Next = child
curChild = child
curChild.Next = first //构成圆环
}
}
return first
}
//显示
func Show(first *Children) {
if first.Next == nil {
fmt.Println("empty circleLink")
return
}
//创建一个辅助指针,帮助遍历
helper := first
for {
fmt.Printf("child[%d] ->", helper.No)
//遍历退出条件 ,当helper.Next = first , 即运行重叠了
if helper.Next == first {
break
}
//helper 向下移动
helper = helper.Next
}
println()
}
func Sum(first *Children) (total int) {
if first.Next == nil {
fmt.Println("empty circleLink")
return
}
//先创建一个辅助指针,帮助遍历
curChild := first
total = 0
for {
total ++
//遍历退出条件 ,当curChild.Next = first , 即运行重叠了
if curChild.Next == first {
break
}
//curChild 向下移动
curChild = curChild.Next
}
return total
}
//编写一个算法,按照要求,在环形链表中留下最后一个人
func josephLink(first *Children, startNo, countNum int) {
//
if first.Next == nil {
fmt.Println("empty link")
return
}
//判断if startNo > 小孩的总数,退出
totalChild := Sum(first)
if startNo > totalChild || startNo <= 0 {
fmt.Println("wrong startNo")
os.Exit(0)
}
//需要定义辅助指针,以帮助删除被点到数的小孩
rear := first
for {
if rear.Next == first { //表示rear已经到了最后
break
}
rear = rear.Next //向前移动
}
//让first移动到startNo的位置,即删除
for i := 1; i <= startNo - 1; i++ {
//同时移动
first = first.Next
rear = rear.Next
}
println()
//开始数countNum,然后就删除first 指向的小孩
for {
//开始数countNum -1 次
for j := 1; j <= countNum - 1; j++ {
first = first.Next
rear = rear.Next
}
fmt.Printf("[%d] removed\n",first.No)
//删除first指向的节点
first = first.Next
rear.Next = first
//退出判断 当rear == first ,说明圈中只有一个小孩了
if rear == first {
break
}
}
fmt.Printf("the last child is [%d]\n",first.No)
}
func main() {
first := AddChild(10)
Show(first)
josephLink(first,6,5)
}
因篇幅问题不能全部显示,请点此查看更多更全内容