设头指针的循环单向队列及其约瑟夫环应用

本文介绍了一个基于循环队列的数据结构实现约瑟夫环问题的解决方案。通过定义结构体和函数来实现循环队列的基本操作,如初始化、判断是否为空、获取队列大小、获取队尾指针、遍历输出队列、队尾入队、队头出队及队列旋转等。最后,利用这些操作实现了约瑟夫环问题,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

typedef struct QNode {
	int data;
	QNode *next;
}QNode;

typedef struct CLQueue {
	QNode *head;
}CLQueue;

void initCLQueue(CLQueue &Q) {	//区别于只有一个结点的自闭环,空队列head->next设为NULL
	Q.head = new QNode;
	Q.head->data = NULL;
	Q.head->next = NULL;
}
bool isEmptyCLQueue(CLQueue Q) {//不采用Q.head->next==Q.head,因为那表示有且仅有一个结点
	if (Q.head->next==NULL)
		return true;
	else
		return false;
}
int getCLQueueSize(CLQueue Q) {	//获取队列长度
	if (isEmptyCLQueue(Q)) {
		return NULL;
	}
	if (Q.head->next == Q.head) {	//只有一个结点时
		return 1;
	}
	int len = 1;
	QNode *tailNode = Q.head->next;
	while (tailNode != Q.head) {
		tailNode = tailNode->next;
		len++;
	}
	return len;
}
QNode* getCLQueueTail(CLQueue Q) {	//获取队尾指针
	int len = getCLQueueSize(Q);
	if (len == 0) {
		return NULL;
	}
	if (len == 1) {
		return Q.head;
	}
	QNode* tailNode = Q.head;
	for (len; len > 1; len--) {
		tailNode = tailNode->next;
	}
	return tailNode;
}
void showCLQueue(CLQueue Q) {	//遍历输出各结点值一遍
	int len = getCLQueueSize(Q);
	if (len == NULL) {
		cout << "Empty!" << endl;
		return;
	}
	QNode* showNode = Q.head;
	for (len; len > 0; len--) {
		cout << showNode->data<<" ";
		showNode = showNode->next;
	}
	cout << endl;
	return;
}
void enCLQueue(CLQueue &Q,int e) {	//队尾入队
	QNode *tailNode = getCLQueueTail(Q);
	if (!tailNode) {	//空插,head已经分配空间,无需再分配
		Q.head->data = e;
		Q.head->next = Q.head;
		return;
	}
	QNode *newNode = new QNode;
	newNode->data = e;
	if (tailNode == Q.head) {	//只有一个结点
		Q.head->next = newNode;
		newNode->next = Q.head;
		return;
	}
	//多个结点
	tailNode->next = newNode;
	newNode->next = Q.head;
	return;
}
int deCLQueue(CLQueue &Q) {	//队头出队
	QNode *tailNode = getCLQueueTail(Q);
	if (!tailNode) {	//空删非法
		cout << "Error: empty delete!" << endl;
		return NULL;
	}
	int e;
	if (tailNode == Q.head) {	//一个结点删除时,无需删除队列本身,只还原成空队列(断开头结点自闭环)
		e = Q.head->data;
		Q.head->data = NULL;
		Q.head->next = NULL;
		return e;
	}
	//多个结点,保存原队头,将队头后移,连接队尾与新队头,删除原队头
	QNode *delNode = Q.head;
	Q.head = Q.head->next;
	tailNode->next = Q.head;
	e=delNode->data;
	delete delNode;
	return e;
}
void rotateCLQueue(CLQueue &Q,int i) {	//转动闭环,使得头指针指向第i个位置,队列元素保持不变
	int len = getCLQueueSize(Q);
	if (!len) {
		cout << "Error: empty rotate!" << endl;
		return;
	}
	if (len == 1) {
		return;
	}
	QNode *curNode = Q.head;
	for (i; i > 1; i--) {
		curNode = curNode->next;
	}
	Q.head = curNode;
	return;
}


int joseph(int num,int first) {	//约瑟夫环
	//num: 总人数,first:第一个报数位置
	CLQueue J; int last;
	initCLQueue(J);
	for (int i = 1; i <= num; i++) {
		enCLQueue(J, i);
	}
	showCLQueue(J);

	do {
		rotateCLQueue(J, first);
		last = deCLQueue(J);
		cout <<last<<" ";
	} while (!isEmptyCLQueue(J));
	cout << endl;
	return last;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值