约瑟夫问题,具体含义通过百度百科/维基百科查阅,分别用数组和链表两种方式实现
注:一下用C++实现,但本质和C一样,只需要在输出、入把cout,cin改成printf,scanf即可
1、用数组实现
主要原理是假设n为总人数,m为间隔,s为起始报数位置,则s = (s+m-1)%n就是第一个出局的人,那么只要把这个人移到最后,s之后的往前移动,n--即可
void Juseph1(int n, int m, int s)
{
int *a = new int[n];//保存n个人的编号(1-n)
//C语言用a = malloc(sizeof(int)*n)
int i;
int j;
int s1 = s;
int temp;
for(i=0; i<n; i++)
a[i] = i + 1;//a[i]存i+1的编号
for(i=n; i>1; i--)
{
s1 = (s1 + m -1) % i;//s1便是每次循环第一个出局的人
if(s1 == 0)//若循环中最后一人出局就不用往前移了
s1 = i;
temp = a[s1-1];
for(j=s1; j<i; j++)
{
a[j-1] = a[j];
}
a[i-1] = temp;
}
for(i=n; i>0; i--)
{
cout << a[i-1] << " ";
//C语言用printf("%d ", a[i-1])
}
cout << endl;
//C语言用printf("\n" )
delete []a;
//C语言用free(a)
}
2、用链表实现
用单向循环链表实现,n表示总人数,出局一个减一个,直到为1
typedef struct List
{int data;
struct List *next;
}List;
List *CreatList(int n)
{
List *p = NULL;
List *head = NULL;
List *tail = NULL;
while(n--)
{
p = new List;
cout<<"please input the data of nodes!"<<endl;
cin>>p->data;
p->next = NULL;
if(head == NULL)
{
head = p;
tail = head;
}
else
{
tail->next = p;
tail = p;
}
}
tail->next = head;
return head;
}
void Display(List *head)
{
List *p = head;
while(p->next != head)
{
cout<<p->data<<" ";
p = p->next;
}
cout<<p->data<<endl;
}
void Juseph(List *head, int n,int m, int s)//n个总个数,m为间隔,s为起始位置
{
List *p = head;
List *q = NULL;
List *temp = NULL;
int i = 0;
int j = 0;
while(p->next != head)
{ j++;
if(j == s)
break;
p = p->next;
}
while(n)
{
i++;
if(i == m)
{
cout<<p->data<<" ";
i = 0;
n--;
temp = p->next;
delete p;
q->next = temp;
p = temp;
}
else
{
q = p;
p = p->next;
}
}
cout<<endl;
head = NULL;
}