约瑟夫退圈问题(循环链表实现)

约瑟夫退圈问题:利用循环链表类实现约瑟夫退圈问题:n 个人 (不同 id)围成一个圈,从 startId(任意数)个开始报数 m(任意数)个 数,数 m 的人出列排成新队列,m 清零,然后又从下一个人开始数 m 个数开始,数到 m 就出列接在新队列尾部,如此重复,直到所有 人都出列为止,请输出出列的次序(依次输出出列人员的编号)。 说明:参数n,stratId和m要通过输入确定,注意要考虑startId和m 大于n的情况

 首先需要写个循环链表

#pragma once
#include

using namespace std;

//结点类模板
template 
class Node{
public:
	T data;
	Node* next;

	Node(T data) :data(data), next(nullptr) {};
};

#pragma once
#include "node.h"

template
class  CircularList {
public:
	Node* head;
	Node* tail;
	int size;
	CircularList() {    //循环链表初始化,尾指针置为空指针,头结点=尾结点
		tail = nullptr;
		head = tail;
		size = 0;
	}

	void tailAdd(T data) {    //尾插  头插在本问题中用不到,就不写了
		Node* p = new Node(data);
		if (tail == nullptr) {    //如果尾指针为空,直接让尾指针=p
			tail = p;
			head = p;
		}
		else {            
			tail->next = p;
			tail = p;
			tail->next = head;
		}
		size++;
	}


	void remove(T data) {    //根据数据删除结点
		while (head->data == data) {
			head = head->next;
			size--;
			if (size == 0)return;
		}
		Node* p = head;
		int i = 1;
		while (p->next && i < size) {
			if (p->next->data == data) {
				if (p->next->next != nullptr)p->next = p->next->next;
				else {
					p->next = nullptr;
					break;
				}
				size--;
			}
			p = p->next;
			i++;
		}

	}

	void printList() {    //遍历链表打印
		Node* p = head;
		int i = 0;
		while (p && i < size) {
			i++;
			cout << p->data << endl;
			p = p->next;
		}
	}
};

#include"circularList.h"

int main() {
	CircularList cl;
	int n, startId, m;
	cin >> n >> startId >> m;
	if (startId > n || m > n) {    //判断startId 
		cout << "输入错误!startId > n 或 m > n" << endl;
	}
	for (int i = 1; i <= n; i++) {
		cl.tailAdd(i);    //插入编号
	}
	Node* p = cl.head;
	int i = 0;
	while (i < startId - 1) {    //找到开始位置
		i++;
		p = p->next;
	}
	i = 1;            //i记录数到了几
	int j = 0;        //j记录已经出列几位
	while (p && j < n) {
		if (i == m) {
			cout << p->data << endl;    //输出编号
			cl.remove(p->data);    //退出链表
			j++;
			i = 0;			
		}		
		i++;
		p = p->next;
	}
	cout << "已全部出列" << endl;
	return 0;
}

你可能感兴趣的:(链表,数据结构)