循环队列解决(报数)约瑟夫环问题

有n个人围成一圈,从第1个人开始,1,2,…,m报数,报至m出局,余下的人继续从1,2,…,m报数,重复之前的流程,要求:求出被淘汰编号的序列,及最后剩下的一人是原来的第几号?
例如:
输入 10
输入  3
输出 3 6 9 2 7 1 8 5 10
输出 4

算法思路:

由于报数方法相当于一个环,所以可以用循环队列来解决,循环队列相当于一个数组,每出队一个人,就让出队后边的数组向前移动一位,最后留下的那个人一定位于数组第一位。

#include 
#include 
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef struct
{
	int *base;
	int front;
	int rear;
	int length;//用来记录队列长度
}*SqQueue;

Status InitQueue(SqQueue Q)//初始化队列
{
	Q->base=(int *)malloc(sizeof(int));
	if(!Q->base) exit(OVERFLOW);
	Q->front=Q->rear=0;
	Q->length=0;
	return OK;
}


Status EnQueue(SqQueue Q,int e,int n)//入队
{
	if((Q->rear+1)%n+1==Q->front) return ERROR;
	Q->base[Q->rear]=e;
	Q->length++;
	Q->rear=(Q->rear+1)%n;
	return OK;
}

int DeQueue(SqQueue Q)//出队
{
	int e=Q->base[Q->front];
	for(int i=Q->front;ilength;i++){
	    Q->base[i]=Q->base[i+1];//将队列每个数向前移动一位,覆盖出队的数
	}
	Q->length--;//由于出队一个数,队列长度减一
	return e;
}

void DestroyQueue(SqQueue Q)//销毁队列
{
	if(Q->base) free(Q->base);
	Q->base=NULL;
	Q->front=0;
	Q->rear=0;
}

int main()
{
	SqQueue Q;
	InitQueue(Q);
	int n,k,e;
	scanf("%d",&n);
	scanf("%d",&k);
	for(int i=1;i<=n;i++){
	    EnQueue(Q,i,n);
	}
	int a=n;//用来记录剩下的人数
	while(a!=1){
	    int b=1;//b用来控制第几个人报数
	    while(b!=k){
	        Q->front=(Q->front+1)%Q->length;
	            b++;
	    }
	    e=DeQueue(Q);
	    printf("%d ",e);
	    a--;
	}
	printf("\n");
	e=Q->base[0];
 	printf("%d",e);
}

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