约瑟夫环问题C++实现:功能需求及代码解析

约瑟夫环问题是一个经典的数学问题,可以描述为:n个人围成一圈,从第1个人开始报数,报到m的人出圈,然后从出圈人的下一个人开始继续报数,直到最后剩下一个人为止。本篇文章将使用C++语言实现约瑟夫环问题,并对代码进行详细解释。

功能需求如下:

  1. **初始化链表头:**定义一个节点,并将其'next'指针指向自身。
  2. **建立循环链表:**根据输入的总人数,创建一个循环单链表,每个节点的'id'依次递增。
  3. **移动节点到开始的序号:**根据输入的开始序号,将'p'和'r'指针移动到对应的节点位置。
  4. **循环出圈:**当链表中的节点数大于1时,循环报数和删除节点,直到只剩下一个节点。
  5. **输出最后剩下的人:**输出最后剩下的节点的'id'号。

代码实现:

#include <iostream>
using namespace std;

class List {
public:
	//链表结构体
	struct node {
		int id;
		node* next;
	};
	int m, startId, n;//m报数的最大值,n总人数,startId开始序号。
	node* p, * r;
	//构造函数:
	List() {
		p = NULL;
	}
	//析构函数:
	~List() {};
	//初始化链表头:
	void startset(node*& m) {
		m = new node;
		m->next = m;
	}
	//建立循环链表(尾插法):
	void setlist(int x) {
		node* q;
		r = p;
		p->id = 1;
		for (int i = 2; i <= x; i++) {
			q = new node;
			q->id = i;
			r->next = q;
			r = q;
		}
		r->next = p;//尾指针指向头节点。
	}
	//核心环节:
	void runlist() {
		int i = 1;
		startset(p);//初始化链表头。
		cout << "请输入总人数:";
		cin >> n;
		cout << "请输入报数最大值:";
		cin >> m;
		cout << "请输入报数开始时的序号:";
		cin >> startId;
		system("pause");
		cout << "依次出列人员的编号:\n";
		setlist(n);//创建循环单列表。
		//移动节点,到开始的那个数:
		while (--startId) {
			p = p->next;
			r = r->next;
		}
		//当圈不为1个人时,循环出圈:
		if (p->next != p) {
			do {
				if (i == m)//报数与m相等时。
				{
					i = 1;
					cout << p->id << "号\n";
					r->next = p->next;
					delete(p);//删除结点。
					p = r->next;
				}
				else//报数不满m时,继续循环。
				{
					r = r->next;
					p = p->next;
					++i;
				}
			} while (p->next != p);
		}
		//到最后剩下的人:
		cout << "最后一位是:" << p->id << "号" << endl;
	}
};
int main() {
	List list;
	list.runlist();
	return 0;
}

代码解析:

  1. 链表结构体定义:
struct node {
	int id;
	node* next;
};

定义了一个名为'node'的结构体,用来表示链表中的节点。每个节点包含一个'id'和一个指向下一个节点的指针'next'。

  1. 初始化链表头:
void startset(node*& m) {
	m = new node;
	m->next = m;
}

该函数用来初始化链表头。首先使用'new'运算符创建一个新的节点,然后将该节点的'next'指针指向自身,形成一个循环链表。

  1. 建立循环链表:
void setlist(int x) {
	node* q;
	r = p;
	p->id = 1;
	for (int i = 2; i <= x; i++) {
		q = new node;
		q->id = i;
		r->next = q;
		r = q;
	}
	r->next = p;//尾指针指向头节点。
}

该函数用来建立循环链表。首先将头节点的'id'设为1,然后使用循环创建其他节点,并将每个节点的'id'设为i。最后将尾节点的'next'指针指向头节点,形成循环链表。

  1. 移动节点到开始的序号:
while (--startId) {
	p = p->next;
	r = r->next;
}

该循环用来将'p'和'r'指针移动到指定的开始节点。每次循环将'p'和'r'指针都向后移动一个节点,直到'startId'减为0。

  1. 循环出圈:
do {
	if (i == m)//报数与m相等时。
	{
		i = 1;
		cout << p->id << "号\n";
		r->next = p->next;
		delete(p);//删除结点。
		p = r->next;
	}
	else//报数不满m时,继续循环。
	{
		r = r->next;
		p = p->next;
		++i;
	}
} while (p->next != p);

该循环用来模拟报数出圈的过程。每次循环都会判断当前报数是否等于'm',如果是则将当前节点删除,并将'r'指针指向下一个节点,否则将'r'和'p'指针都向后移动一个节点。循环条件为'p->next != p',即链表中只有一个节点时停止。

  1. 输出最后剩下的人:
cout << "最后一位是:" << p->id << "号" << endl;

循环结束后,'p'指针指向最后剩下的节点,输出该节点的'id'号。

总结:

本篇文章详细介绍了约瑟夫环问题的C++实现,包括链表的初始化、循环链表的建立、节点移动、循环出圈和最后剩下的人的输出。提供了完整的代码示例,并对每个功能进行了详细解释。希望本文能帮助读者更好地理解约瑟夫环问题,并掌握相关代码实现。

约瑟夫环问题C++实现:功能需求及代码解析

原文地址: https://www.cveoy.top/t/topic/qvPh 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录