问题背景
C链表的实现思路
我们可以通过声明一个结构体,让后根据输入的值N动态的创建N个节点,让后将
它们链成一个循环链表。通过next指针操作模拟数人数。让后删除进行下一个节
的指向,作为第一个数数节点继续开始。直到链表中还剩一个节点的时候。
实现代码
void ysf_problem_ListSolve(int num){
//first create a loop-node-link
List head=(List)malloc(sizeof(Node));
List p=head;
int i;
for(i=0;i<num;i++){
List new=(List)malloc(sizeof(Node));
new->number=i+1;
p->next=new;
p=new;
}
p->next=head->next;
p=head->next;
head->next=NULL;
free(head);
//开始约瑟夫老头的算法
while(p->next!=p){
List del=p->next->next;
p->next->next=del->next;
p=del->next;
free(del);
}
printf("最后一个人的编号是:%d\n\n",p->number);
}
注:这种算法虽然符合人的思维,但是有一个缺点就是占用太多的内存。
其实我们还可以通过数组的方法来实现。
数组实现思路
我们可以声明一个N长度的数组,数组中的存值对应着每个人的编号。每次我们
只要将数组的第三号元素删除,让后将前两个值用变量保存,将第四个即以后的
元素值移到最前面。再把保存的两个值加到尾部。就这样模拟人的删除操作,直到
还剩最后两个的时候就可以确定最后一个要数的人是谁了。
实现代码
void ysf_problem_ArrSolve(int num){
int *number=(int *)malloc(sizeof(int)*num);
int i;
int step=0;
for(i=0;i<num;i++)
number[i]=i+1;
while(number[EndNum]){//EndNum是宏定义
int one=number[0];
int two=number[1];
for(i=EndNum;i<num-step;i++){
number[i-EndNum]=number[i];
number[i]=0;
}
number[i++-EndNum]=one;
number[i-EndNum]=two;
step++;
}
printf("最后一个人的编号是:%d\n\n",number[1]);
}
工程代码
#include <stdio.h>
#include <stdlib.h>
#define EndNum 3
typedef struct node{
int number;
struct node *next;
}Node,*List;
void ysf_problem_ArrSolve(int num);
void ysf_problem_ListSolve(int num);
int main(int argc, char *argv[]) {
int num;
printf("\t约瑟夫问题\n");
printf("----------------------------------\n");
s: printf("退出:0\n");
printf("请输入人数(>0):");
scanf("%d",&num);
if(num&&num>0){
ysf_problem_ListSolve(num);
//ysf_problem_ArrSolve(15);
goto s;
}else if(num==0){
exit(0);
}else{
goto s;
}
return 0;
}
void ysf_problem_ListSolve(int num){
//first create a loop-node-link
List head=(List)malloc(sizeof(Node));
List p=head;
int i;
for(i=0;i<num;i++){
List new=(List)malloc(sizeof(Node));
new->number=i+1;
p->next=new;
p=new;
}
p->next=head->next;
p=head->next;
head->next=NULL;
free(head);
//开始约瑟夫老头的算法
while(p->next!=p){
List del=p->next->next;
p->next->next=del->next;
p=del->next;
free(del);
}
printf("最后一个人的编号是:%d\n\n",p->number);
}
void ysf_problem_ArrSolve(int num){
int *number=(int *)malloc(sizeof(int)*num);
int i;
int step=0;
for(i=0;i<num;i++)
number[i]=i+1;
while(number[EndNum]){
int one=number[0];
int two=number[1];
for(i=EndNum;i<num-step;i++){
number[i-EndNum]=number[i];
number[i]=0;
}
number[i++-EndNum]=one;
number[i-EndNum]=two;
step++;
}
printf("最后一个人的编号是:%d\n\n",number[1]);
}