约瑟夫环!编 号是1,2,??,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向 自1开始顺序报数,报到m时停止报数。

流程:

⑴建立模型,确定存储结构;
⑵ 对任意 n个人,密码为 m,实现约瑟夫环问题;
⑶出圈的顺序可以依次输出,也可以用一个数组存储。

示意图:

约瑟夫环!编 号是1,2,??,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向 自1开始顺序报数,报到m时停止报数。_第1张图片约瑟夫环!编 号是1,2,??,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向 自1开始顺序报数,报到m时停止报数。_第2张图片

设计:

首先,设计实现约瑟夫环问题的存储结构。由于约瑟夫环问题本身具有循环性质,考虑采用循环链表,为了统一对表中任意结点的操作,循环链表不带头结点。其次,建立一个不带头结点的循环链表并由头指针 first 指示。
建立一个结构体node,然后给他开辟一个储存空间;利用头指针head标记链表,利用尾指针向后移将建立的结点连接成我们需要的单循环链表,约瑟夫问题中的人数个数即为链表的长度,链表中node->num 编号n,node->data为每个人的密码。建立单循环链表后,通过初始报数上限找到出列的结点,输出该结点的node->num值,将该结点中的data中数作为新密码开始下一个步的开始,将该结点从链表中删除,并释放该结点的空间。重复此过程,直到剩下最后一个结点,就直接将该结点中的num值输出,删除该结点,并释放该结点的空间。输出的num值即为约瑟夫中人的编号。

代码:

typedef struct Node 
{ 
int data; 
int num;
struct Node *next; 
}Node,*Link; 

void InitList(Link &L){//创建一个空的链表
    L=(Node *)malloc(sizeof(Node));
	if(!L)
		exit(1);
	L->data=0;
	L->num=0;
	L->next=L;
}                                
void CreateList(int n, Link &L){//初始化链表
    Link p,q;
	q=L;
		printf("请输入这%d个人的初始密码分别为:",n);
	for(int i= 1;i <= n;i++){
	     p=(Node *)malloc(sizeof(Node));
		 if(!p)
			 exit(1);
		 scanf("%d",&p->data);
		 p->num=i;
		 L->next=p;
		 L=p;
	}
	L->next=q->next;
	free(q);
}
void Locate_m(Link &L,int m,int n){//找位置
    Link p,q;
	p=L;
	for(int i=1;i<=n;i++){
       for(int i=1;i< m;i++)
	   p=p->next;
	   q=p->next;
	   m=q->data;
	    printf("%d ",q->num);
	   p->next=q->next;
	   free(q);
}
}
int main(){
   Link L,p,q;
   int n,m;
   L=NULL;
   InitList(L);
   printf("初始密码为:");
   scanf("%d",&m);
   printf("总人数为:");
   scanf("%d",&n);
   CreateList(n,L);
   printf("正确的输出为:");
      Locate_m(L,m,n);
   printf("\n");
   return 0;
}

你可能感兴趣的:(c语言)