约瑟夫问题
问题描述
编号为1 - N的N个人围坐在一起形成一 个圆圈从第P个人开始,依次按照顺时针的方向报数,数到第M的人出列,直到最后剩下一个人。打印出出局人的编号。
解决思路
建立一个双向循环链表,我们用链表的节点代替人数,通过寻找删除来模拟约瑟夫问题。
图示如下:
第一次查找删除:
第二次查找删除:
第三次查找删除:
第四次查找删除:
第五次查找删除:
第六次查找删除:
第七次查找删除:
代码实现
// An highlighted block
#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
int num;
struct Node *next;
struct Node *ahead;
}Node;
Node *Create(int N);
Node *Search(Node *head,int P);
Node *Release(Node *head,int M);
int main()
{
int M, P, N;
scanf("%d%d%d", &N,&M,&P);//p起始点m释放点
Node *head = Create(N);
head = Search(head, P);
while (head->next != head)
{
head = Release(head, M);
}
printf("%d",head->num);
return 0;
}
Node *Create(int N)
{
int n=1;
Node* node = (Node*)malloc(sizeof(Node));//new Node;
node->num = n;
Node * head = node;
Node* tail = head;
while (n++ <
N)
{
node = (Node*)malloc(sizeof(Node));
node->num = n;
tail->next = node;
node->ahead = tail;
tail = tail->next;
}
tail->next = head;
head->ahead = tail;
return head;
}
Node *Search(Node* head, int P)
{
while (head->num != P)
{
head = head->next;
}
return head;
}
Node *Release(Node* head, int M)
{
int count = 1;
Node* temp = head;
while (count < M)
{
temp = temp->next;
count++;
}
temp->ahead->next = temp->next;
temp->next->ahead = temp->ahead;
printf("%d", temp->num);
head = temp->next;
delete temp;
return head;
}