约瑟夫(Josephu)问题,环形链表

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)

结果打印:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员D日常

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值