[C语言、C++]数据结构作业:用双向链表和0-1变量实现折返约瑟夫问题

请使用合适的数据结构实现:使用“折返报数”方式的Joseph问题。
所谓“折返报数”Joseph问题是指:
(1)n(n>1)个人排成一队,从1到n依次编号;从1到m循环报数,报到m(m>1)者退出;
(2)游戏先从编号为1的人(队头)开始依次从前向后报数,当报数到达队尾时,立即改为从后往前报数;
(3)当从后往前报数到达队头时,立即改为从前往后报数;
(4)如此“折返”报数,直到队列中只剩下1人为止,即为胜者;
要求:
(1)从键盘输入n和m;
(2)依次输出游戏过程中退出人的编号;
(3)输出获胜者编号;
例:
输入:n=5;m=3
输出:
3 4 2 5
胜者:1

#include <iostream>
using namespace std;
typedef struct LinkNode {
	int data;
	LinkNode* next;
	LinkNode* pre;
}*LinkList;
void InitLinkList(LinkList& L) {
	L = NULL;
}
void CreatRear(LinkList& L,int n) {
	L = NULL;
	if (n <= 0)return;
	else {
		L = new LinkNode;
		cin >> L->data;
		L->pre = NULL; L->next = NULL;
		if (n > 1) {
			LinkNode* r = L;
			for (int i = 1; i < n; i++) {
				LinkNode* s = new LinkNode;
				cin >> s->data;
				r->next = s;
				s->pre = r;
				r = r->next;
			}
			r->next = NULL;
		}
	}
}
void Returning_Joseph(int n, int m) {
	LinkList L; InitLinkList(L);
	CreatRear(L, n);
	LinkNode* p = L; int isBack = 0;
	for (int i = 0; i < n - 1; i++) {
		int j = 0;
		while (j < m - 1) {
			if (isBack == 0) {
				while (p->next != NULL && j < m - 1) {
					p = p->next; j++;
				}
				if (p->next == NULL)isBack = 1;
			}
			if (isBack == 1) {
				while (p->pre != NULL && j < m - 1) {
					p = p->pre; j++;
				}
				if (p->pre == NULL)isBack = 0;
			}
		}
		cout << p->data << " ";
		LinkNode* r = p;
		if (p->next == NULL || p->pre == NULL) {
			if (p->next == NULL) {
				p = p->pre;
				delete(p->next);
			}
			else {
				p = p->next;
				delete(p->pre);
			}
		}
		else {
			p->pre->next = p->next;
			p->next->pre = p->pre;
			if (isBack == 0)p = p->next;
			else p = p->pre;
			r->next = NULL; r->pre = NULL;
			delete(r);
		}
	}
	cout << endl;
	cout << p->data << "是胜者"; 
}
int main(){
	Returning_Joseph(5, 3);
}

此题难点在于在约瑟夫问题的基础上摒弃了环的结构,而是改为“折返”,所以自然想到双向链表(无头),但难点在于,如何让程序知道现在是向前遍历还是向后遍历呢?

这里我们设一个初始值 isBack==0,来判断现在是向前还是向后遍历,如果超过了边界,那么更改isBack的值进入到另一个向前遍历的分支即可,如此循环,即可实现“折返” 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值