约瑟夫环问题 (c / c++)

来源:互联网 发布:哪个软件可以升级win10 编辑:程序博客网 时间:2024/06/07 01:32

                                             

            约瑟夫环问题是一道经典的数据结构的题目,问题描述为:编号为1,2,......,n的n个人按顺时针方向围坐在一张圆桌周围,每个人持有一个密码(正整数)。一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报到m的那个人出列,将他的密码作为新的m值,从他顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列,如此下去,直至圆桌周围的人全部出列为止。


           我选择用双向链表来存储每个人的信息,每个结点存储的内容有:name[20],password,flag(顺逆时针的标志)以及prior和next指针。

typedef struct person

{

     char name[20];

     int password;

     int flag;

     struct person *prior, *next;

}Node;

           在初始化整个链表时,每个人的password和flag是通过随机数随机获取的,flag=0表示按顺时针旋转报数,flag=1表示按逆时针旋转报数。初始化完毕,开始报数,第一个报数的人由用户输入获得,遍历整个链表,找到与输入的名字相同的那个结点,将其password,flag记录下来,再定义两个指针,一个指向刚刚找到结点的下一个(或前一个)结点,一个在以后的遍历中,将指向被删掉的结点。要注意的是双向链表的删除有两个语句。

定义:

#include <stdio.h>#include <stdlib.h>#include <time.h>#define N 10typedef struct person{char name[20];int password;int flag;struct person *prior;struct person *next;}Node;

初始化:

Node *create_link(int n){int i=1;Node *head;Node *s,*p;srand((int)time(NULL));head = (Node *)malloc(sizeof(Node));printf("请输入姓名:");getchar();scanf("%[^\n]",head->name);head->password = rand()%N+1;head->flag = rand()%2;p = head;while(i < n){s = (Node *)malloc(sizeof(Node));printf("请输入姓名:");getchar();scanf("%[^\n]",s->name);s->password = rand()%N+1;s->flag = rand()%2;p->next = s;s->prior = p;p = s;i++;}p->next = head;head->prior = p;       output(head);return head;}

run:

void run(Node *head,Node *q,int n){int i=0;int password = q->password;int flag = q->flag;Node *s,*r;s = r = q;while(i<(n-1)){s = r;if(flag == 0){r = s->next;while(password > 0){s = s->next;password--;}}else{r = s->prior;while(password > 0){s = s->prior;password--;}}flag = s->flag;password = s->password;printf("此次出局的是:%s\n",s->name);s->prior->next = s->next;s->next->prior = s->prior;free(s);i++;}printf("最后留下的是%s\n",r->name);}

输出函数:

void output(Node *head){Node *p = head;printf("flag=0表示顺时针,flag=1表示逆时针\n");while(p->next != head){puts(p->name);printf("password:%d\n",p->password);printf("flag:%d\n\n",p->flag);p = p->next;}puts(p->name);printf("password:%d\nflag:%d\n\n",p->password,p->flag);}


main函数:

int main(int argc, char *argv[]){int n,i=0,flag=1;char name[20];Node *head,*p;printf("请输入总人数:");scanf("%d",&n);head = create_link(n);printf("请输入第一位开始者的姓名\n");getchar();scanf("%[^\n]",name);p = head;do{while(i<n){if(strcmp(p->name,name)==0){  flag = 0;break;}else{p = p->next;i++;}}if ( i == n){printf("未找到该人,请重新输入:");getchar();scanf("%[^\n]",name);p = head;i = 0;}}while(flag == 1);run(head,p,n);return EXIT_SUCCESS;}

运行结果:


在这里,特别告诉大家一个要注意的地方,我在接收name的时候,没有用gets(),(ps:因为它总是提示:警告: 不建议使用‘gets’(声明于 /usr/include/stdio.h:638) [-Wdeprecated-declarations]),这是因为gets是不会去检查字符串的长度的,那么如果输入的字符串过长,则会造成溢出现象,所以这里我换用了scanf(“%[^\n]”,name);这样就会避免溢出所带来的可怕后果。关于这个“scanf扫描集”,建议大家阅读这篇博客,写的很清楚.博客地址

下面是用c++实现的约瑟夫环,代码思想基本一样,只是用了类,本人菜鸟一只,大家就凑合着看吧。

#include <stdio.h>#include <stdlib.h>#include <time.h>#include <string.h>#define N 10typedef struct person{char name[20];int password;int flag;struct person *prior;struct person *next;}node;class people{private:int   n;node *head;node *p;public:void create_link();void run();void output();void find_p();void getvalue();};void people::create_link(){int i=1;node *s,*r;srand((int)time(NULL));head = new node();printf("请输入姓名:");getchar();scanf("%[^\n]",head->name);head->password = rand()%N+1;head->flag = rand()%2;r = head;while(i < n){s = new node();printf("请输入姓名:");getchar();scanf("%[^\n]",s->name);s->password = rand()%N+1;s->flag = rand()%2;r->next = s;s->prior = r;r = s;i++;}r->next = head;head->prior = r;       }void people::output(){node *p = head;printf("flag=0表示顺时针,flag=1表示逆时针\n");while(p->next != head){puts(p->name);printf("password:%d\n",p->password);printf("flag:%d\n\n",p->flag);p = p->next;}puts(p->name);}void people::run(){int i=0;int password = p->password;int flag = p->flag;node *s;while(i<(n-1)){s = p;if(flag == 0){p = s->next;while(password > 0){s = s->next;password--;}}else{p = s->prior;while(password > 0){s = s->prior;password--;}}flag = s->flag;password = s->password;printf("此次出局的是:%s\n",s->name);s->prior->next = s->next;s->next->prior = s->prior;i++;}printf("最后留下的是%s\n",p->name);}void  people::find_p(){int i = 0;int flag = 1;char name[20];printf("请输入第一位开始者的姓名\n");getchar();scanf("%[^\n]",name);p = head;do{while(i<n){if(strcmp(p->name,name)==0){  flag = 0;break;}else{p = p->next;i++;}}if ( i == n){printf("未找到该人,请重新输入:");getchar();scanf("%[^\n]",name);p = head;i = 0;}}while(flag == 1);}void people::getvalue(){printf("请输入总人数:");scanf("%d",&n);}int main(int argc, char *argv[]){people s;s.getvalue();s.create_link();s.find_p();s.run();return 0;}


原创粉丝点击