class-notes/2207/C语言/约瑟夫环.md
2025-02-20 22:02:41 +08:00

1.7 KiB
Raw Blame History

写法1-暴力写法 使用数组来模拟队列

#include <stdio.h>

/*
约瑟夫环人数n编号m

队列 先进先出
a 3 1 2

头 下标 
尾 下标
*/
//rear尾巴 front头
int queue[200] = {0};
int rear=0, front=0;
//用来拿到队列最前面的元素值
int get(){
	int temp = queue[front];
	queue[front++] = 0;
	return temp;
}
//用来在队列末尾差值
void put(int n){
	queue[rear++] = n;
}
//打印队列当前状态
void print(){
	int i;
	for(i=0;i<200;i++){
		if(queue[i] != 0){
			printf("%d ", queue[i]);
		}
	}
	printf("\n");
}
//判断队列是否为空
int isEmpty(){
	int count = 0;
	int i;
	for(i=0;i<200;i++){
		if(queue[i] != 0){
			count++;
		}
	}
	return count;
}
int main(){
	int n, m;//n人数 m为弹出的编号
	int i, count = 0;
	scanf("%d %d", &n, &m);
	for(i=1;i<=n;i++){
		put(i);
	}
	print();
	while(isEmpty()){
		count++;
		if(count % m == 0){
			printf("%d ", get());
		}else{
			put(get());
		}
	}

	return 0;
}

写法2-循环队列 使用数组模拟循环队列

#include <stdio.h>

/*
使用数组模拟循环队列
*/

int main(){

	int joseph[100] = {0};
	int n, m, count = 0;//n:人数 m:编号数 count:已出局的人数
	int i = 1, k = 0;//i:用来遍历数组 k用来记录已经报数的编号
	printf("请输入人数以及编号数:");
	scanf("%d %d", &n, &m);
	for(i = 0; i < n;i++){
		joseph[i] = i+1;//标记为1 则为非空代表当前下标编号有人
	}

	i = 0;
	while(n > count){
		if(joseph[i]){
			k++;//报数
			if(k%m == 0){//判断是否弹出
				printf("%d ", joseph[i]);
				joseph[i] = 0;//标记为0 代表当前下标的人已经弹出
				count ++;
			}
		}
		i = (i+1)%n;
	}
	printf("\n");

	return 0;
}