Joseph的问题(c++循环链表)

作者在 2016-05-12 16:05:46 发布以下内容

先看看这个问题怎么来的

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特後,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

[不得不说他很机智啊!!!]

今天复习了链表。。。复习的时候感觉像重新学了一遍,所以听课多重要!!!


问题:编号1,2,3......n的n个人,顺时针围着圆桌(很明显首尾相接,是个循环链表),每个人手里有个数字(随机的),设定一个初始数,然后从编号1的人开始从1到n的顺序报数,报到初始数的人离开,他手中的数为下一个筛选数,离开的人的顺时针方向的人又开始从1到n的报数,报到筛选数的人离开,不停的进行直到只剩最后一个人,他就是winner!!

所以1个人有两个变量,一个是自己的编号,一个是手里的号码

链表涉及循环和删除操作,不复杂(直接看代码)

#include<iostream>
using namespace std;

struct LinkNode
{
	int data;//,密码
	int num;//编号
	LinkNode *next;

};
class LinkList
{
public:
	LinkList();
	bool Append(int, int);
	bool Delete(int);
	~LinkList();

private:
	LinkNode *tail;

};

LinkList::LinkList()
{
	tail = NULL;
}
//创建单循环链表
bool LinkList::Append(int a1, int a2)
{
	LinkNode *p = new LinkNode;//新建节点
	p->data = a1;
	p->num = a2;
	//判断是否已存在节点
	if (tail==NULL)//否
	{
		tail = p;//保存p点
		tail->next = tail;//指向自己,形成循环
	}
	else//是
	{
		p->next = tail->next;//插入新节点p,为新节点的后驱赋值
		tail->next = p;//形成循环
		tail = p;//新节点变为首节点
	}
	return true;

}
//删除结点,链接断开的节点
bool LinkList::Delete(int m)
{
	LinkNode *p = tail, *q;//tail是最后一个编号
	while (p != p->next)//剩下一个人不执行
	{
		for (int k = 1; k < m; k++)//找到报M的人
		{

			p = p->next;
		}

		q = p->next;//用q记录这个人
		p->next = q->next;//将两个节点连接
		cout << q->num << " ";
		m = q->data;//删除这个人
		delete q;
	}
	cout << p->num << " ";
	delete p;
	return true;
};
LinkList::~LinkList()
{
}
 void Creat(LinkList &y, int &n){
	int a1, a2, i;
	cout << "请输入" << n << "个密码:" << endl;
	for (i = 1; i <= n; i++){
		cin >> a1;
		a2 = i;
		y.Append(a1, a2);
	}
}
 int main(){
	LinkList y;
	int j, n, m;
	n=10;
	m=4;
	Creat(y, n);
	y.Delete(m);
	system("pause");
	return 0;
}

算法不能只看代码,一定要跟着程序逻辑,一步步纸上跟着计算(自己在纸上画个链表图,然后手写增删改的代码,一定要弄清楚当前指向的是哪个节点),也可以单步调试,主要是弄清楚为什么要这样,还有变量的值

我的打砖块大业还没完成......




算法之路前进 | 阅读 10399 次
文章评论,共0条
游客请输入验证码
浏览36860次
最新评论