Josephu问题是:设置编号为:1,2,3…n个人围在一起,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,他的下一位又从1开始报数,数到m的那个人又出列,以此类推,知道所有人都出列,由此产生一个出队编号的序列。
package utils
import (
"fmt"
)
type Children struct{
No int //编号
Next *Children //指向下一个小孩的指针
}
go代码演示:
//添加小孩数,生成环形链表
func Add(num int) *Children{
first := &Children{}
if num < 1 {//传入的num值不正确
return first
}
current := &Children{}
for i := 1; i <= num; i++{
child := &Children{
No : i,
}
if i == 1 {
first = child
}else{
current.Next = child
}
current = child
current.Next = first
}
return first
}
/**
* child: 链表
* startNo: 从第startNo开始数,
* countNum: 数countNum个后出列
*
* 返回剩余的最后一个结点
*
* */
func RemainList(first *Children, startNo int, countNum int) *Children{
newChild := &Children{}
if first.Next == nil {//空链表
return newChild
}
//统计链表总数,并且让last指向环形列表的末尾结点
total := 1
last := first //指向环形链表末尾结点
for {
if last.Next == first{
break
}
last = last.Next
total++
}
if startNo > total{
return newChild
}
//开始位置定位到startNo
for i := 1; i <= startNo; i++{
first = first.Next
last = last.Next
}
//从这个节点开始数
temp := first
for{
//定位到数countNumde位置
for i := 1; i <= countNum - 1; i++{
first = first.Next
last = last.Next
}
fmt.Printf("从%d结点开始数 %d 个数到%d \n", temp.No, countNum, first.No)
//删除countNum位置的节点
first = first.Next
last.Next = first
if first == last{//头和尾重合
newChild = first
break
}
fmt.Println("结点出列【删除】", first)
temp = first
}
return newChild
}
//链表
func List(first *Children){
if first.Next == nil{
fmt.Println("空链表")
return
}
temp := first
for{
fmt.Printf("[No = %d] ==>", temp.No)
if temp.Next == first{
//fmt.Printf("[No = %d] 【首尾相连】\n", temp.Next.No)
break
}
temp = temp.Next
}
fmt.Println()
return
}
测试代码:
node := utils.Add(10)
utils.List(node)
//从第2个结点开始数,每次向后数8个结点后移除当前结点
newNode := utils.RemainList(node, 2, 3)
utils.List(newNode)
结果打印: