Go数据结构--约瑟夫问题

package main

import "fmt"

//约瑟夫问题

// Boy 定义小孩结构体
type Boy struct {
	no int
	Next *Boy
}

//编写一个函数,创建单向的环形链表
//num :环形链表的元素个数
//*Boy :返回该环形链表的第一个小孩的指针

func CreateCircle(num int) *Boy {
	//创建一个空节点
	first := &Boy{} //这个指针指向第一个元素
	curBoy := &Boy{} //这个指针指向

	//元素个数判断
	if num < 1 {
		fmt.Println("元素个数不能小于1")
		return first
	}

	//循环的构建这个链表
	for i := 1; i <= num; i++ {
		boy := &Boy{
			no: i,
		}

		//第一个小孩比较特殊
		if i == 1 {
			first = boy //指针就不能动了,所以好需要一个辅助指针 curBoy
			curBoy = boy //帮忙的指针 curBoy
			//形成闭环
			curBoy.Next = first
		}else {
			//当前是1	新的2
			curBoy.Next = boy
			//curBoy向后面移动1位
			curBoy = boy
			//最后这个指向开头形成环
			curBoy.Next = first
		}
	}
	return first
}

// ShowCircle 显示环形单向链表
func ShowCircle(first *Boy)  {
	//空链表判断
	if first == nil {
		fmt.Println("链表为空")
		return
	}

	//first是一个指针,我们还需要一个指针
	curBoy := first
	for  {
		fmt.Printf("小孩的id=%d",curBoy.no)
		//当到达最后一个时候,退出
		if curBoy.Next == first {
			break
		}
		curBoy = curBoy.Next
	}
}

// first 头节点
// startNo 开始数数的位置
// stepNum 每次数几个,步长

func PlayGame(first *Boy,startNo int,stepNum int)  {
	//1.空链表判断
	if first.Next == nil {
		fmt.Println("空的链表,没有小孩")
		return
	}

	//2.需要定义辅助指针,帮助我们删除元素
	tail := first	//tail 尾巴,一开始他俩实在一起的
	//3.我们移动tail,让tail指向first的尾巴
	for  {
		if tail.Next == first {
			break//此时移动到尾巴了
		}
		tail = tail.Next
	}

	//4.让first移动到startNo[后面我们删除元素,就以first为准]
	for i := 1; i <= startNo - 1; i++ {
		//这两个标记都往下走
		first = first.Next
		tail = tail.Next
	}

	//5.开始数stepNum,然后就删除first当前所在的元素
	//删除一个元素的操作是这样的
	//a:先让first向下走一步,把这个需要删除的元素空出来
	// first = first.Next
	//b:让尾部tail的Next指向新的first,跳过空出来的元素,这样就把空出来的元素删除了
	//tail = first

	for  {
		//这两个标记同时按照步长往下走,一步一步走,总移动stepNum-1的
		for i := 1; i <= stepNum-1; i++ {
			first = first.Next
			tail = tail.Next
		}
		fmt.Printf("编号%d的元素被剔除-->",first.no)
		//执行删除 a,b两步
		first = first.Next
		tail.Next = first

		//当只剩下一个元素的时候就退出
		//即 两个标记重合了,因为我们在前面让两个标记分开了
		if tail == first {
			break
		}
	}
	fmt.Printf("最后剔除的元素是%d",first.no)
}
func main() {
	first := CreateCircle(500)
	ShowCircle(first)
	fmt.Println()
	fmt.Println("显示结束")

	PlayGame(first,20,31)
	fmt.Println()

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值