【问题描述】
简化的约瑟夫环 (Joseph) 问题。编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个正整数的密码。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此循环,直至圈内的所有人全部出列为止。
【基本要求】
利用循环链表模拟此过程,按照出列的顺序打印各人的编号
【测试数据】
m=20,n=7;圈内人所持密码: 3,1,7,2,4,8,4。
【测试结果】
正确的结果应为6,1,4,7,2,3,5
问题分析:
首先定义一个结构体,其中包含三个成员变量:编码num,密码code,指针*next
要输入参数:人数n 初始密码m 循环密码,其中循环密码可以存在一维数组中
基本思路:
编写YSF函数(约瑟夫)
首先创建结点数为n的循环链表,同时填充数据域(num和code)
然后开始循环,一个个出局
代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct YSFnode{
int num;
int code;
struct YSFnode* next;
}Node,*list;
YSF(int n, int m){//传入人数n,初始密码m
//输入密码,用数组存储密码
int a[n];
int i;
for(i = 0; i< n;i++){
printf("输入密码:");
scanf("%d",&a[i]);
}
//创建链表
list head = NULL, p = NULL, tmp = NULL;
head = (list)malloc(sizeof(Node));
p = head;
p->num = 1;
p->code = a[0];
for(i = 1;i < n;i++){
//创建链表
tmp = (list)malloc(sizeof(Node));
tmp->num = i+1;//输入编码
tmp->code = a[i];//输入密码
p->next = tmp;//链接
p = p->next;//后移
}
p->next = head;//循环链表
p = head;//pc重新指向头指针
//出局循环
while(p->next != p){//循环结束条件是只剩下一个结点,所以后面还要输出最后这个结点的编码
for(i = 1; i<m ;i++){
//用p指针指向要出局的人
tmp = p;
p = p->next;
}
printf("%d ",p->num);//打印编码
m = p->code;//更新密码
tmp->next = p->next;//删除结点
p = p->next;//后移
}
printf("%d",p->num);//打印最后一个编码
}
int main(){
int n,m;
printf("输入人数和初始密码(空格隔开):");
scanf("%d %d",&n,&m);
YSF(n,m);
return 0;
}
运行: