猴子选大王(约瑟夫环问题)

#include <iostream>
using namespace std;

struct Node//链表节点结构体
{
	int n;//节点数据
	Node *next;//一个结构体指针
};

Node * Create(const int);//声明创建链表的函数
void Conduct(Node *, const int ,const int);//声明筛选结果的函数
void free(Node *);//声明释放内存的函数

int main(int argc, char const *argv[])
{
	int m, n;//定义m表示节点总数,n表示报数是报到的最大数字
	Node *p = NULL;//定义空结构指针
	while (1)
	{
		cout << "请输入猴子个数及报数的最大数字" << endl;
		cin >> m >> n;//输入数据

		if (m == 0)
			return 0;

		p = Create(m);//调用函数创建循环链表

		Conduct(p, m, n);//调用函数筛选猴王
	}

	free(p);
	return 0;
}

Node * Create(const int n)
{
	int i = 1;//定义i计数
	Node *head = NULL;//定义head头指针默认指向null
	Node *previous;//定义表示上一个节点的指针
	Node *current;//定义表示当前节点的指针
	while (i <= n)//循环n次,为每个猴子创建节点
	{
		current = new Node();//开辟新的节点内存空间
		current->n = i;//给每个节点赋值
		if (head == NULL)
			head = current;//如果头节点为空,则应该让头结点指向新开辟的节点地址
		else
			previous->next = current;//如果已经不是第一个节点,就让上一个节点的‘next’指向新的节点,才能串到一块

		previous = current;//再将上一个位置的指针向后移一位,因为上面的操作使链表增长一个节点
		i++;
	}
	current->next = head;//将最后一个节点的‘next’指向头节点,实现链表的循环
	return head;//返回链表头指针个主函数
}

void Conduct(Node *head, const int i, const int x)
{
	Node *p = NULL;//定义临时指针
	Node *previous;//定义表示上一个节点的指针
	p = head;//获取链表入口
	int t = 1;//定义t模拟猴子报数
	int count = i;//定义count表示链表中的有效节点数量
	while(p != NULL)//如果链表不为空,则执行如下操作
	{
		if(t%x == 0)//表示如果这个猴子正好报到尾数,t表示正好报道数,x表示报数的最大值
		{
			previous->next = p->next;//删除表示这个猴子的节点
			count--;//链表中的有效节点减一
		}

		previous = p;//记录当前节点
		p = p->next;//节点继续向后移动

		t++;//报数在增加,是一直在增加的,用求余去实现报数的循环

		if(count == 1)//如果最后只剩下一个有效节点
			break;//终止继续排除节点
	}
	cout << "猴王是" << p->n << "号\n" << endl;//输出最后留下的节点表示猴王
}

void free(Node *t)
{
	Node *p = t;
	while (p != NULL)
	{
		delete(p);//释放节点
		p = p->next;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值