约瑟夫环有很多的变种,其中有一个就是,输入要救的人数,请给出这些人合理的序号以至于他们都能得救。
下面是我用循环链表写的一个比较粗糙的算法,就当作为一个记录,等有时间再优化一下代码并且再用数组的方法做一下,最后希望能够收集约瑟夫环的大多数的问题来一个整理,大家见笑了。
//
//
// 利用链表j解决约瑟夫问题
//
//
#include <stdio.h>
#include <stdlib.h>
#define Number 41 // 人数
typedef struct Node
{
int id ;
struct Node * next ;
} Node ;
// 建立一个基于循环链表的约瑟夫环
void CreateJosephCircle( Node * head )
{
for( int i = 0 ; i < Number ; i++ )
{
Node * node = (Node*)malloc(sizeof(Node)) ;
if( !node )
{
printf("申请内存失败!") ;
exit(0) ;
}
node->id = i + 1 ;
node->next = NULL ;
Node * p = head ;
Node * q = p ;
while( p != NULL )
{
q = p ;
p = p->next ;
}
q->next = node ;
if( i == Number - 1 )
{
node->next = head->next ; // 使最后一个结点的下一个结点为第一个结点
}
}
}
int main()
{
int order[Number] ; // 存储自杀顺序
int length = 0 ;
int n ; // 要救的人的书目
Node * head = (Node*)malloc(sizeof(Node)) ;
if( !head )
{
printf("申请内存失败!") ;
exit(0) ;
}
head->next = NULL ; // 初始化
CreateJosephCircle( head ) ; // 创建约瑟夫环
//==========================================================
Node * p = head->next->next ; // 遍历约瑟夫环输出数据
while( p != head->next )
{
printf("%d ",p->id ) ;
p = p->next ;
}
printf("%d\n" , p->id ) ;
//=============================================================
Node * q = head->next ;
Node * r = q ;
while( q != q->next ) // 用指针q来遍历整个约瑟夫环,当只剩一个结点的时候结束遍历
{
for( int i = 0 ; i < 2 ; i++ )
{
r = q ;
q = q->next ;
}
r->next = q->next ;
order[length++] = q->id ; // 记录下自杀的顺序
printf("%d " , q->id ) ;
free( q ) ;
q = r->next ;
}
printf("%d " ,q->id ) ; // 输出最后一个结点中的信息
order[length] = q->id ;
printf("\n请输入一共要救的人的数量:") ;
scanf("%d" , &n) ;
printf("可以为被救的人安排如下顺序:\n") ;
for( int j = 0 ; j < n ; j++)
{
printf("%d " , order[Number-j-1] ) ;
}
printf("\n") ;
return 0 ;
}