约瑟夫环(数组、链表)
约瑟夫环(数组)
设有SIZE=30个人围坐一圈,从某个人开始报数,数到N=7的人出列,接着往下从下一个人开始重新报数,数到N=7的人又出列,直到所有的人出列为止。输出出列的顺序。
实验代码
#include<stdio.h>
#define SIZE 30
int main()
{
int index=0;
int step=1;
int count=0;
int outs[SIZE]={0};
int flag[SIZE]={0};
index=0,step=1,count=0;
while(count < SIZE)
{
if(step==7)
{
outs[count] = index+1;
count++;
step = 0;
flag[index] = 1;
}
index = (++index)%SIZE; //求余,循环遍历
if(flag[index]==0)
{
step++;
}
}
for(count=0;count<SIZE;count++)
{
printf("%d\n",outs[count]);
}
return 0;
}
Joseph 环(链表)
*问题描述:编号是 1,2,……,n 的 n 个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值 m,从第一个仍开始顺时针方向自 1 开始顺序报数,报到 m 时停止报数。报 m 的人出列,将他的密码作为新的 m 值,从他在顺时针方向的下一个人开始重新从 1 报数,如此下去,直到所有人全部出列为止。设计一个程序来求出出列顺序。
*要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
*测试数据:m 的初值为 20,n=7 ,7 个人的密码依次为 3,1,7,2,4,7,4,首先 m=6,则正确的输出是什么?
实验代码
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int key;//每个人持有的密码
int num;//这个人的编号
struct Node* next;//指向下一个节点
}Link;
Link* InitList()//创建一个空的链表
{
Link* L;
L = (Link*)malloc(sizeof(Link));
L->key = 0;
L->num = 0;
L->next = L;
return L;
}
Link* Creater(Link* L, int n)//初始化链表
{
Link* p, * q;
int i;
q = L;
for (i = 1; i <= n; i++) //构建链表
{
p = (Node*)malloc(sizeof(Node));
printf("第%d个人的密码:", i);
scanf("%d", &p->key); //成员密码存放到key中
p->num = i; //编号存放到num中
L->next = p; //将p的地址赋值给L的指针域
L = p; //将p的值赋值给L
}
L->next = q->next; //构建为环状
free(q);
return L;
}
void Output(Link* L, int n, int m)
{
Link* p, * q;
int i, j;
p = L;
printf("\n结果序列为:");
for (i = 1; i <= n; i++)
{
for (j = 1; j < m; j++)
p = p->next; //p指到目的结点前一个结点
q = p->next; //q指向目的结点
m = q->key;
printf("%d ", q->num);
p->next = q->next; //此两步是为了释放目的结点,即删除
free(q);
}
}
int main()
{
Link* L, * S;
int n, m;
L = InitList(); //构造出一个只有头结点的空链表
printf("请先输入总人数:");
scanf("%d", &n); //总共的人数n
printf("请确定开始时的报数上限值:");
scanf("%d", &m); //初始密码为m
S = Creater(L, n);//建立好一个约瑟夫环
Output(S, n, m);
}