循环链表实现约瑟夫环(c语言)

问题描述如下:

编号为1,2…n的n个人按顺时针方向围坐一圈,每人持有一个密码。一开始人选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,直到所有人出列。设计程序求出列顺序。

问题分析:

  1. 数据结构的选择:
    将编号num,密码data,下个人的指针next封装成一个结构体,代表一个“人”。围成一圈可以用循环链表实现,但是尾插法构造链表时尾元结点指向首元结点会避免绕圈时遇到头结点的情况。
  2. 删除操作与判空操作一同写在main函数中。
    若p->next=p则该结点p已经是最后一个人,所以在循环结束后不要忘记最后一个剩下的人。删除操作一定要先找到要删元素的前驱结点,前驱结点指向p->next->next.
    完整代码如下:
#define ERROR -1
#define TRUE 1
#define OVERFLOW -1
typedef int Elemtype;
typedef int Status;
typedef struct LNode{
 Elemtype data;//密码 
 int num;//编号 
 struct LNode *next;
}LNode, *LinkList;
LinkList Initlinklist(LinkList &l){
 l=(LinkList)malloc(sizeof(LNode));
 l->next=l;
 return l;
}
void  CreateFromTail(LinkList l){
 LinkList r=l, s;
 Elemtype c;
 int flag=1, k=1;
 printf("请输入每个人的密码:\n");
 //getchar();
 //printf("%c\n", c);
 while(flag==1){//先建立节点再设置next 
  scanf("%d", &c);
  if(c!=-1){
   s=(LinkList)malloc(sizeof(LNode));
   s->data=c; 
   s->num=k++;
   r->next=s;//r指向上一个s; 
   r=s;
  }
  else{
   flag=0;
   r->next=l->next;
  }
 }
}
int main(){
 int m, counter=0;
 LinkList l, p, q;
 Initlinklist(l);
 CreateFromTail(l);
 cout<<"请输入初始报数上限值:"<<endl;
 cin>>m;
 p=l->next;
 while(p->next!=p){
  counter=1;
  while(counter!=m-1){
   counter++;
   p=p->next;
  }
  q=p->next;
  p->next=q->next;
  m=q->data;
  cout<<"本次出列的人是:"<<endl;
  cout<<q->num<<endl;
  p=p->next;
  free(q);
 }
 cout<<"本次出列的人是:"<<endl;
 cout<<p->num;
}

效果如下:
在这里插入图片描述

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值