数据结构与算法分析 c++11 练习3.6 JosePhus 问题(Josephus problem)


练习

  3.6 JosePhus 问题(Josephus problem)是下面的游戏:N个人编号1~N,围坐成一个圆圈。从1号人开始传递一个热土豆。经过M次传递后拿着热土豆的人被清除离座,围坐的圆圈锁紧,由坐在后面的人拿起热土豆继续进行游戏。最后剩下的人获胜。因此,如果M=0和N=5,则游戏人依序被清除,5号游戏人获胜。如果M=1 和N=5,那么被清除的人的顺序是2,4,1,5.

a. 编写一个程序解决在M和N为一般的值下的Josephus 问题,应使所编程序尽可能地高效率,要确保各个单元都能被清除。

b. 这个程序的运行时间是多少?

c. 如果M=1,这个程序的运行时间又是多少? 对于N的一些大值(N>100000), delete 例程如何影响该程序的速度?


          解答: 执行1000次,需要1.26 秒。


#include <iostream>
#include <chrono>     // 求运行时间的库

using namespace std;
using namespace chrono;


typedef struct LNode
{
	int data;
	struct LNode *link;
	LNode()
	{
		data = 0;
		link = NULL;
	}
}LNode,*LinkList;


/*
*  n 为总人数 
*  k 为第一个开始传递的人
*  m 为拿到土豆被剔除的人
*/

int Josephus(int n, int k, int m)
{
	// pnode 为当前节点,prenode 为辅助节点,指向pnode 的前驱节点,curr 为头结点
	if(n < 0 || k < 0 || m < 0)
	return -1;
	LinkList pnode, prenode, curr;
	pnode = new LNode();
	pnode->data = 1;
	pnode->link = pnode;            //建立循环链表
	curr = pnode;
	for (int i = 2; i <= n; i++) {
		LinkList temp = new LNode();
		temp->data = i;
		temp->link = curr->link;
		curr->link = temp;
		curr = temp;
	}
	prenode = curr;
	while (k--) {
		prenode = pnode;       //prenode 是pnode的前一个节点
		pnode = pnode->link;   //移动节点pnode 到第k个元素开始
	}

	while (n>1)
	{
		// for 是移动m个位置,pnode会移动到m的位置,prenode 是pnode 的前一个节点
		for (int s = m; s>0;--s)
		{
			prenode = pnode;
			pnode = pnode->link;
		}
		prenode->link = pnode->link;                     //删除pnode节点
		cout << "deleted node is " << pnode->data << endl;
		free(pnode);                              //释放空间
		pnode = prenode->link;                     // 从prenode 的下一个节点开始,数一个m个节点的值
		n--;
	}
	return pnode->data;


}


int main()
{
	//k=0,表示从第一个人开始,m表示每次移动m个人
	//	josePhus(5, 0, 1);
	int winner;
	auto start = system_clock::now();
	for(size_t i=0;i<1000;++i)
	   winner=Josephus(5,0,1);
	auto end = system_clock::now();
	auto duration = duration_cast<microseconds>(end - start);
	cout << " Consume:  " << double(duration.count())*microseconds::period::num / microseconds::period::den << " s(秒)" << endl;
	
	cout <<"The winner is "<< winner << endl;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值