约瑟夫问题 -面向对象的思想解答

#include <iostream>
using namespace std;
#define SIZE 41  //链表长度 (总节点个数)


class PersonNode //节点
{
private:
	int num; //当前节点的编号
	bool isDead;//是否在已死(出圈表示已死)
	PersonNode * pNextNode;//下一个节点
public:
	void setNum(int num)
	{
		this->num = num;
	}
	void setIsDead(bool isDead)
	{
		this->isDead = isDead;
	}
	void setNextNode(PersonNode * nextNode)
	{
		this->pNextNode = nextNode;
	}

	int getNum()
	{
		return this->num;
	}
	bool getIsDead()
	{
		return this->isDead;
	}

	PersonNode * getNextNode()
	{
		return this->pNextNode;
	}
};
class LinkedList //链表
{
private:
	int size;//链表大小
	PersonNode *headNode;//头节点
public:
	void setSize(int size)
	{
		this->size = size;
	}

	void setHeadNode(PersonNode * headNode)
	{
		this->headNode = headNode;
	}

	PersonNode * getHeadNode()
	{
		return this->headNode;
	}

	//遍历所有的节点
	void showList()
	{
		PersonNode *tempNode = headNode;
		for (int i = 0; i < this->size; i++)
		{
			cout << tempNode->getNum() << endl;
			tempNode = tempNode->getNextNode();
		}
	}
	//显示存活的节点
	void showNoDead()
	{
		PersonNode *tempNode = headNode;
		for (int i = 0; i < this->size; i++)
		{
			if (!tempNode->getIsDead())
			{
				cout << tempNode->getNum() << endl;
			}
			
			tempNode = tempNode->getNextNode();
		}
	}

	//销毁
	void destroy()
	{
		PersonNode *tempNode = headNode;
		for (int i = 0; i < this->size; i++)
		{
			PersonNode *nextNode = tempNode->getNextNode();
			delete tempNode;
			tempNode = nextNode;
		}
	}
};

//初始化 SIZE个节点编号1到SIZE,最后一个节点的下一个节点指向第一个节点,返回链表
LinkedList *  init()
{
	PersonNode * headNode = new PersonNode();
	headNode->setIsDead(false);
	headNode->setNum(1); //头节点

	PersonNode* tempNode = headNode; //中间变量
	for (int i = SIZE; i >=2; i--)
	{
		PersonNode* node = new PersonNode;
		node->setIsDead(false);
		node->setNum(i);
		node->setNextNode(tempNode);
		tempNode = node;
		if (i == 2)
		{
			headNode->setNextNode(node); //头节点指向第二个节点
		}
	}
	LinkedList * list = new LinkedList();
	list->setHeadNode(headNode);
	list->setSize(SIZE);
	return list;
}

void test1()
{
	LinkedList * list = init();
	list->showList();
	list->destroy();
	delete list;
}
//约瑟夫 
void test2(int maxNum)
{
	int i = SIZE;//存活的节点数 初始值为链表总长度
	LinkedList * list = init();
	PersonNode *tempNode = list->getHeadNode(); //游标 最开始指向头节点
	int num = 1; //数数 从1开始
	while (true)
	{
		
		tempNode = tempNode->getNextNode(); //游标移动
		if (!tempNode->getIsDead()) //跳过死的
		{
			num++;//num +1
		}
		if (num == maxNum)
		{
			tempNode->setIsDead(true);//数到3,该节点死了
			cout << tempNode->getNum() << "->死了" << endl;
			i--;//存活的节点减1
			num = 0;//归0
		}
		
		if (i <maxNum)//存活的最后的节点
		{
			break;
		}
	}

	list->showNoDead();//显示最后存活的节点
	list->destroy();
	delete list;
}

int main(int argc, char * argv[])
{
	//test1();
	test2(3);
	system("pause");
	return 0;
}

好的,下面是C++面向对象思想编写约瑟夫问题的全部代码: ```c++ #include <iostream> using namespace std; // 定义一个结点类 class Node { public: int data; Node *next; Node(int d) { data = d; next = NULL; } }; // 定义一个约瑟夫问题类 class Josephus { public: int n, m; // n表示总人数,m表示出列的间隔 Node *head, *tail; // 队列的头和尾结点 Josephus(int n, int m) { this->n = n; this->m = m; head = tail = NULL; } // 初始化队列 void init() { for (int i = 1; i <= n; i++) { Node *p = new Node(i); if (head == NULL) { head = tail = p; } else { tail->next = p; tail = p; } } tail->next = head; // 队列首尾相连 } // 出列操作 void out() { Node *p = head, *pre = tail; while (n > 1) { for (int i = 0; i < m - 1; i++) { pre = p; p = p->next; } pre->next = p->next; delete p; p = pre->next; n--; } cout << "最后一个出列的人是:" << p->data << endl; } }; int main() { int n, m; cout << "请输入总人数和出列的间隔:"; cin >> n >> m; Josephus j(n, m); j.init(); // 初始化队列 j.out(); // 开始出列操作 return 0; } ``` 解释一下代码: 首先定义了一个结点类 `Node`,用于构建链表;然后定义了约瑟夫问题类 `Josephus`,其中包含了总人数 `n`、出列的间隔 `m`、队列的头和尾结点 `head`、`tail`。类中有三个方法:`init()` 用于初始化队列;`out()` 用于出列操作;main() 函数中创建了一个 `Josephus` 对象,调用 `init()` 和 `out()` 方法,完成约瑟夫问题的求解。 具体实现细节可以参考代码注释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值