约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
使用数据结构中的循环队列来解决这个问题:
Status.h
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
main.h
#include <iostream>
using namespace std;
#include "Status.h"
typedef int ElemType;
typedef struct
{
ElemType *base;
int front;
int rear;
int MAXSIZE;
}SqQueue;
Status InitQueue(SqQueue& Q,int n)
{
Q.base = new ElemType[100];
if(!Q.base)
{
cout << "创建队列失败!";
return ERROR;
}
Q.front=Q.rear=0;
Q.MAXSIZE = n+1;//MAXSIZE是总人数+1,是为了留出一个空位置来放置rear
return OK;
}
void QueueTraverse(SqQueue Q)
{
int i;
i=Q.front;
while(i!=Q.rear)
{
cout<<Q.base[i]<<" ";
i=(i+1)%Q.MAXSIZE;
}
cout<<endl;
}
Status EnQueue(SqQueue& Q,ElemType e)
{
if((Q.rear+1)%Q.MAXSIZE==Q.front)
{
cout << "队列已满!";
return ERROR;
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1)%Q.MAXSIZE;
return OK;
}
Status DeQueue(SqQueue& Q,ElemType& e)
{
if(Q.front==Q.rear)
{
cout << "队列为空!";
return ERROR;
}
e = Q.base[Q.front];
Q.base[Q.front] = 0;
Q.front = (Q.front+1)%(Q.MAXSIZE-1);//因为此时的MAXSIZE比总的人数大1,所以需要减去1
return OK;
}
int main()
{
int n,m,i=1;
SqQueue Q;
ElemType e;
cout << "请输入n个人(n<=100):";
cin >> n;
if(n>100 || n<1)
{
cout << "输入人数错误!";
return 0;
}
InitQueue(Q,n);
while(i<=n)//入队操作
{
EnQueue(Q,i);
i++;
}
cout << "\n此时的序列顺序为:";
QueueTraverse(Q);
cout << "\n请输入第m个人出队(1<=m<=n):";
cin >> m;
if(m>n || m<1)
{
cout << "m输入错误!";
return 0;
}
cout << endl;
int Count = n;//用来记录剩下的人数
while(Count != 1)
{
i = 1;//i用来控制是第几个人报数
while(i != m)//当i的值不等于m的值时
{
Q.front = (Q.front+1)%(Q.MAXSIZE-1);//因为此时的MAXSIZE比总的人数大1,所以需要减去1
if(Q.base[Q.front] != 0)//当此时不为0的话,i++用来控制第几个人
{
i++;
}
}
DeQueue(Q,e);
while(Q.base[Q.front] == 0)//当此时为0的时候,循环找到下一个不为0的位置
{
Q.front = (Q.front+1)%(Q.MAXSIZE-1);
}
cout << "序号:" << e << "出局!\n";
Count--;
}
DeQueue(Q,e);
cout << "\n最后一个是:" << e << endl;
return 0;
}
测试: