数据结构-实验4 约瑟夫环

其实我之前写过约瑟夫环的问题,当时还不是特别会。
现在的约瑟夫环是升级版的。
【问题描述】
约瑟夫环问题的描述是:编号为 1,2,…,n 的 n 个人按顺时针方向围坐一
圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限 m,从第
一个人开始按顺时针方向自 1 开始顺序报数,报到 m 时停止报数。报 m 的人出
列,将他的密码作为一个新的 m 值,从他在顺时针方向上的下一个人开始重新从
1 报数,如此下去,直至所有人全部出列为止。请设计一个程序求出列顺序。
【基本要求】
利用单向循环链表存储结构模拟此过程,按照出列顺序打印出各人的编号。
【测试数据】
(1)输入:m 的初值为 20;
n=7; 7 个人的密码依次为 3,1,7,2,4,8,4。
输出:正确的出列顺序为 6,1,4,7,2,3,5。
(2)输入:m 的初值为 20;
n=7;
密码输入依次为 3,1,7,2,4,8。
输出:密码输入有误,请重新输入密码:
密码输入依次为 3,1,7,2,4,8,4 时,
正确的出列顺序为 6,1,4,7,2,3,5。
代码实现:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>

#define OK 1
#define FALSE 0
#define ERROR 0

typedef int Status;
typedef int ElemType;

typedef struct YUE
{
 ElemType data;
 ElemType loa;
 struct YUE *next;
}LNode,*LinkList;

Status Create(LinkList &L)//创建
{
 L=(LinkList)malloc(sizeof(LNode));
 if(!L)
 {
  printf("申请空间错误!\n");
  return ERROR;
 }
 printf("申请空间成功!\n");
 L->next=L;
 return OK;
}

LinkList GetElem(LinkList L,int i)
{
 LNode *p;
 p=L;
 int j;
 for(j=0;j<i;j++)
 {
  p=p->next;
 }
 return p;
}

Status Length(LinkList L)
{
 LNode *p;
 p=L;
 int i=1;
 while(p->next!=L)
 {
  p=p->next;
  ++i;
 }
 return i;
}

Status Insert(LinkList &L,int i,ElemType e)
{
 if(i<1||i>Length(L)+1)
 {
  printf("插入位置错误!\n");
  return ERROR;
 }
 if(i==1)
 {
  L->data=e;
  L->loa=i;
  L->next=L;
  return OK;
 }
 LNode *p=GetElem(L,i-2);
 LNode *s;
 s=(LinkList)malloc(sizeof(LNode));
 s->loa=i;
 s->data=e;
 s->next=p->next;
 p->next=s;
 return OK;
}

Status Ling(LinkList L)
{
 int i;
 int count=Length(L);
 LNode *p=L;
 for(i=0;i<Length(L);i++)
 {
  if(p->data==0)
  {
   count--;
  }
  p=p->next;
 }
 return count;
}

Status Play(LinkList &L,int m)
{
 int i;
 LNode *p=L;
 LNode *q;
 LNode *tail;
 while(p!=p->next)
 {
  for(i=1;i<m;i++)
  {
   tail=p;
   p=p->next;
  }
  printf("%d->",p->loa);
  m=p->data;
  tail->next=p->next;
  q=p;
  p=p->next;
  free(q);
 }
 printf("%d",p->loa);
 return OK;
}

Status shuchu(LinkList L)
{
 LNode *p=L;
 int i;
 for(i=0;i<Length(L)+1;i++)
 {
  printf("%d号密码是%d\n",p->loa,p->data);
  p=p->next;
 }
 return OK;
}

Status Clear(LinkList L)
{
 LNode *p,*q;
 p=L->next;
 while(p!=L)
 {
  q=p->next;
  free(p);
  p=q;
 }
 p->next=L;
 return OK;
}

int main()
{
 LinkList L;
 Create(L);
 int m;
 printf("输入m的初值:\n");
 scanf("%d",&m);
 getchar();
 printf("m的初值是%d\n",m);
 int n;
 printf("输入人数:\n");
 scanf("%d",&n);
 getchar();
 int i;
 ElemType e;
 char ch;
 int flag;
 while(1)
 {
  flag=0;
  printf("输入%d个人的密码:\n",n);
  int j;
  for(i=1;i<=2*n-1;i++)
  {
   scanf("%c",&ch);
   if(ch=='\n'&&i<2*n-1)
   {
    flag=1;
    break;
   }
   if(ch<='9'&&ch>='0')
   {
    j=(i+1)/2;
    e=ch-'0';
    Insert(L,j,e);
   }
  }
  if(flag==1)
  {
   printf("密码输入有误,请重新输入密码:\n");
   Clear(L);
  }
  else
  {
   break;
  }
 }
 printf("%d个人的密码依次是:\n",n);
 shuchu(L);
 printf("正确的出列顺序为:");
 Play(L,m);
 return 0;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值