在控制台下实现约瑟夫环

 

二、基本要求

 

在控制台下实现约瑟夫环。

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

(1)m 的初值由用户输入,n值可以由用户输入可从读入的文件中统计。

(2)每个人应至少包含的信息:姓名、编号、密码。

(3)参照线性表的实现完成此程序。

(4)打印”约瑟夫环“的初始顺序信息,含有编号、姓名、密码。

(4)用户可选择按姓名或按编号打印出列顺序。

(6)本题提交整个程序的实现代码。

 

 

==========================头文件========================

#ifndef JOSEPHUS_H
#define JOSEPHUS_H

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

#define HEAD_OF_FROM "编号            姓名              密码"  //从文件读入时,忽略文件头

typedef struct Penson //每一个人的基本信息
{
 int ID;
 char name[10];
 int code;
}Penson;
typedef struct Josephus //单循环链表
{
 Penson p;
 struct Josephus *next;
}SeqList;

SeqList *Creat(int n,Penson *P);//构造单循环链表
void OutQueue(SeqList *tail,int num ,int code);//删除节点,约瑟夫环的规则
int Open_File(int n,int m);//打开文件,从中读入需要的信息

 


#endif

======================函数实现========================

#include "Josephus.h"

SeqList *Creat(int n,Penson *P,int m)
{
 SeqList *head = (SeqList *)malloc(sizeof(SeqList));//头节点
 SeqList *rear,*q;//采用尾插法

 if (!head)//验证分配成功
 {
  exit(0);
 }
 rear = head;

 for (int i = 0;i< n;++i)
 {
  q = (SeqList *)malloc(sizeof(SeqList));
  if (!q)
  {
   exit(0);
  }
  q->p.code = P[i].code;//数据域分配
  q->p.ID = P[i].ID;
  strcpy(q->p.name,P[i].name);
  //指针域分配
  rear->next = q;//尾指针的指针域指向q
  rear = q;// 尾指针一直指向最后一个
 }
 rear->next = head->next;//构成单循环链表,尾指针指向头节点

 OutQueue(head,n,m);//由约瑟夫环规则,删除节点
 return head;
}

void OutQueue(SeqList *head,int n ,int m)
{
 int choice = 1;
 printf("请选择按何种方式显示出列顺序:/n[0]按姓名/n[1]按编号/n/n请输入你的选择(0-1):");
 scanf("%d",&choice);

 printf("/n出列顺序为:/n");
 {
  SeqList *p;
  while (n!=1)//直到最后一个节点的时候,停止循环
  {
   m = (m-1)%n +1;//简化计算机的操作,节省空间复杂度,密码比人数大的时候,让链表少转几圈
                             //第一个节点的m值特殊处理
   for (int i = 1;i<m;++i)
   {
    head = head->next;  //依次循环
   }
   p = head->next;
   if (choice == 0)
   {
    printf("%s/n",p->p.name);
   }else{
    printf("%d/n",p->p.ID);
   }

   head ->next = p->next;
   m = p->p.code;//传递密码··把密码覆盖为新的m值
   free(p);//删除节点
   p = NULL;//将p赋新值,也可不用
   --n;//计数器
  }
 }
 if (choice == 0)
 {
  printf("%s/n",head->p.name);
 }else{
  printf("%d/n",head->p.ID);
 }
 //printf("%d/n",head->p.ID);
 free(head);//释放链表,避免悬垂指针
 head = NULL;
}
int Open_File(int n,int m)//文件操作
{
 int i=0,j=0;
 char *filename = "c://a.txt";//文件地址
 Penson P[10];
 FILE *fp = fopen(filename,"r");//只读方式打开

 errno = 0;

 if (!fp)
 {
  fprintf(stderr,"打开文件失败,Error code : %s/n",strerror(errno));
  return -1;
 }
 fseek(fp,sizeof(HEAD_OF_FROM),SEEK_SET);
 i = 0;
 while (!feof(fp)&&i<n)
 {
  fscanf(fp,"%d %s %d/n",&P[i].ID,P[i].name,&P[i].code);
  i++;
 }
 printf("/n约瑟夫环的初始顺序信息为:/n编号/t姓名/t 密码/n");
 for (j = 0;j<n;j++)
 {
  printf(" %d/t%s/t%d/n",P[j].ID,P[j].name,P[j].code);
 }
 printf("/n");

 Creat(n,P,m);//调用构造链表的函数

 fclose(fp);
}


=============================主函数=========================

#include "Josephus.h"

int main(void)
{
 int m,n;

 printf("请输入m和n的初值:");
 scanf("%d %d",&m,&n);

 Open_File(n,m);

 system("pause");
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值