A. DS循环链表—约瑟夫环(Ver. I - A)

A. DS循环链表—约瑟夫环(Ver. I - A)
时间限制
1s
内存限制
128MB
题目描述

N个人坐成一个圆环(编号为1 - N),从第S个人开始报数,数到K的人出列,后面的人重新从1开始报数。问最后剩下的人的编号。
例如:N = 3,K = 2,S = 1。2号先出列,然后是1号,最后剩下的是3号。
要求使用循环链表实现。

输入

测试数据有多组

每组包括3个数N、K、S,表示有N个人,从第S个人开始,数到K出列。(1 <= N <= 10^6,1 <= K <= 10,  1 <= S <= N)


输出

出列的人的编号



输入样例1 
13 3 1
3 2 1
输出样例1
3 6 9 12 2 7 11 4 10 5 1 8 13
2 1 3

该题主要考察数据结构循环链表的使用,在定义循环链表时,与普通单链表的定义不同的是,我们需要让尾结点指向头结点(不是head),这里需要用到的还有循环链表的删除操作,这也有与单链表不同的地方,我们需要特殊考虑//分为当链表中只有一个元素时,删除链表第一个结点(不是头结点),删除链表尾结点,其他情况,否则会出现丢失head的情况

这里分享一篇我看到的较好的文章C语言数据结构篇——单循环链表的创建,插入,节点删除,打印等操作_Demo不是emo的博客-优快云博客_循环单链表的创建

#include<iostream>
using namespace std;

class Node {
public:
	int num;
	Node* next;

	Node() {
		next = NULL;
	}
};

class Clinklist {
public:
	Node* head;
	int len;

	Clinklist() {
		head = new Node();
		head->next = NULL;
		len = 0;
	}

	void create(int n) {
		Node* p = head;
		for (int i = 1; i <= n; i++) {
			Node* node = new Node();
			node->num = i;
			node->next = p->next;
			p->next = node;
			p = p->next;
		}
		p->next = head->next;//创建循环链表的关键:让尾结点指向头结点(不是head)
		len = n;
	}

	bool delNode(Node* target) {//注意这里需要分为四种情况讨论,否则会出现丢失头结点head的情况
		//分为当链表中只有一个元素时,删除链表第一个结点(不是头结点),删除链表尾结点,其他
		Node* pcur = head->next;//指向第一个结点(不是头结点)
		Node* plast=head->next;//指向最后一个结点
		while (plast->next != pcur) {
			plast = plast->next;
		}
		if (len == 1) {
			head->next = NULL;
		}
		else if (target == pcur) {
			head->next = pcur->next;
			plast->next = pcur->next;
		}
		else if (target == plast) {
			Node* pre = pcur;
			while (pre->next != plast) {
				pre = pre->next;
			}
			pre->next = pcur;
		}
		else {
			Node* pre = pcur;
			while (pre->next != target) {
				pre = pre->next;
			}
			Node* q = pre->next;
			pre->next = q->next;
			free(q);
		}
		return true;

	}

	bool getOut(int s,int k) {
		if (!(s >= 1 && s <= len)) {
			return false;//判断s是否合法
		}
		//先找到第s个人;
		Node* p = head->next;
		int i = 1;
		while (i != s) {
			p = p->next;
			i++;
		}
		//开始报数
		while (len != 1) {
			int num = 1;
			while (num != k) {
				num++;
				p = p->next;
			}
			cout << p->num << ' ';
			Node* q = p;
			p = p->next;//下一个人
			delNode(q);//删除找到的结点
			len--;
		}
		cout << p->num << endl;//最后一个人直接输出即可
		return true;
	}
};


int main()
{
	Clinklist clinklist;
	int n, k, s;
	while (cin >> n >> k >> s) {
		clinklist.create(n);
		clinklist.getOut(s,k);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZZWWWFFF_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值