链表的应用--约瑟夫环问题

一、实验目的
本实验是有关线性表的链式存储结构的应用,通过C语言中提供的结构指针来存储线性表,利用malloc函数动态地分配存储空间。
通过对本实验的学习,可以理解线性表在链序存储结构下的操作方法。
二、实验内容
设计一个程序求出约瑟夫环的出列顺序。约瑟夫问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每个人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m 值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。例如,n=7,7个人的密码依次为:3,1,7,2,4,8,4,m的初值取6,则正确的出列顺序应为6,1,4,7,2,3,5。要求使用单向循环链表模拟此出列过程。
三、程序分析
约瑟夫环的大小是变化的,因此相应的结点也是变化的,使用链式存储结构可以动态的生成其中的结点,出列操作也非常简单。用单向循环链表模拟其出列顺序比较合适。
用结构指针描述每个人:
struct Joseph
{int num;/环中某个人的序号/
int secret;/环中某个人的密码*/
struct Joseph next;/指向其下一个的指针/};
1)初始化约瑟夫环:
调用函数struct Joseph *creat()生成初始约瑟夫环。在该函数中使用head 指向表头。输入序号为0时结束,指针p1指向的最后结束序号为0的结点没有加入到链表中,p2 指向最后一个序号为非0 的结点(最后一个结点)。
2)报数出列:
调用函数voil sort(struct Joseph * head,int m),使用条件p1->next!=p1判断单向链表非空,使用两个指针变量p1和p2,语句p2=p1;p1=p1->next;移动指针,计算结点数(报数);结点p1出列时直接使用语句:p2->next=p1->next,取出该结点中的密码作为新的循环终值。
四、程序源代码

#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct joseph)
        //by Jelly Liu
        
        struct joseph{
        	int  num;
        	int secret;
        	struct joseph *next;
        };
        struct joseph *creat(){
        struct joseph *head,*p1,*p2;
        p1=p2=(struct joseph *)malloc(LEN);
        scanf("%d,%d",&p1->num,&p1->secret);
        head=p1;
        while(p1->num!=0){
        p1=(struct joseph *)malloc(LEN);
        p2->next=p1	;
        scanf("%d,%d",&p1->num,&p1->secret);
        if((p1->num)!=0) p2=p1;
        }
        p2->next=head;
        /*
        int i=0;
        for(;i<p2->num;p2=p2->next,i++)
        printf("%d,%d",p2->num,p2->secret);
        */
        return (head);	
        
        }
        void sort(struct joseph *head,int m){       	
        struct joseph *p1,*p2;
        int n=0;
        p1=p2=head;	
          while((p1->next)!=p1){ 
            n++  ;
           if(n==m-1){   
          	p2=p1;
          	p1=p1->next;
          	printf("%d->",p1->num);
          	m=p1->secret;
          	p2->next=p1->next;
          	p1=p1->next;
          	n=0;
          }
          else p1=p1->next;  
          } 
          printf("%d",p1->num);	 
        }  
        int main(int argc, char *argv[]) {
        int m;
        struct joseph *p;
        p=creat();
        scanf("%d",&m);
        sort(p,m);
        		
        	return 0;
        }
#define NULL 0
#define LENGTH sizeof(struct Joseph)
#include "stdlib.h"
#include "stdio.h"
struct Joseph
{int num;
int secret;
struct Joseph *next;
};/*定义结点num为序号,secret为密码*/
/*创建初始链表函数*/
struct Joseph *creat()
{struct Joseph *head;
struct Joseph *p1,*p2;
int n=0;
p1=p2=(struct Joseph *)malloc(LENGTH);
scanf("%d,%d",&p1->num,&p1->secret);
head=NULL;

while(p1->num!=0)
{n=n+1;
if(n= =1)head=p1;
else p2->next=p1;
p2=p1;
p1=(struct Joseph *)malloc(LENGTH);
scanf("%d,%d",&p1->num,&p1->secret);
}
p2->next=head;
return(head);
}
/*报数出列*/
void sort(struct Joseph * head,int m)
{struct Joseph *p1,*p2;
int i;
if(head==NULL)
printf("\n链表为空!\n");
p1=head;
while(p1->next!=p1)
{for(i=1;i<m;i++)
{p2=p1;p1=p1->next;}
p2->next=p1->next;
m=p1->secret;
printf("%d  ",p1->num);
p1=p2->next;
}
if(p1->next= =p1)
printf("%d ",p1->num);
}
main()
{struct Joseph *head;
int m;
printf("\n输入数据:数据格式为序号,密码\n输入0,0为结束\n");
head=creat();
printf("输入 m值\n");
scanf("%d",&m);
if(m<1)printf("error! 请输入一个合法的 m值!");
printf("出列的序号是:\n");
sort(head,m);
}

五、实验结果
最后程序运行结果如下所示:
输入数据:数据格式为序号,密码
输入0,0为结束
1,3↙<回车>
2,1↙<回车>
3,7↙<回车>
4,2↙<回车>
5,4↙<回车>
6,8↙<回车>
7,4↙<回车>
0,0↙<回车>
输入m值
6↙<回车>
出列的序号是
6→1→4→7→2→3→5

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值