约瑟夫环

#include<stdio.h>
#include<stdlib.h>
struct student
  {
    int number;  //每个人的编号
    int flag;  // 标注是不是li4n0
    struct student *next;
  };
struct student *create(int student_member, int m);
void delete(struct student *pold);
struct student *find(struct student *head, int n);

int main(void)
{
  int student_number = 0;
  int n = 0;  // 报到n即出列
  int m = 0;  // li4n0站在第一个同学顺时针方向的第m位
  scanf("%d%d%d", &student_number, &n, &m);
  struct student *head = create(student_number, m);
  struct student *pold;
  int i=student_number;  // 剩余人数

  while (i > n)  //当人数大于n
  {
    pold = find(head, n-2);  // 找到这个同学的前面一个人
    if (1 == pold->next->flag)  // 如果这个人正好是li4n0
    {
      printf("YES");
      exit(0);  // 结束程序
    }
    head = pold->next->next;  // 让出列的同学的下一个同学作为排头继续循环
    delete(pold);  //让出列的同学出列
    i--;
  }
  printf("NO");
  
  return 0;
}

struct student *create(int student_member,int m)
{
  struct student *head = NULL, *pnew, *ptail;
  int i = 0;
  pnew = (struct student*)malloc(sizeof(struct student));  // 创建链表头节点
  pnew->number = i;  // 第一个同学设为编号0
  if (m == i)  // 如果这个同学就是li4n0
    pnew->flag = 1;  // 那么把他标注为1
  else
    pnew->flag = 0;
  head = pnew;
  ptail = pnew;
  while (i < student_member - 1)  // 创建余下链表
  {
    pnew = (struct student*)malloc(sizeof(struct student));
    i++;
    if (m == i)  // 如果这个同学就是li4n0
      pnew->flag = 1;  // 那么把他标注为1
    else
      pnew->flag = 0;
    pnew->number = i;
    ptail->next = pnew;
    ptail = pnew;
  }
  ptail->next = head;  //让最后一个同学与第一个同学连接
  
  return head;  // 返回第一个同学
}

void delete(struct student *pold)  //出列 pold为出列同学前面的同学
{
  struct student *p;
  p = pold->next;
  pold->next = pold->next->next;  // 让前一节点指向后一节点
  free(p);  // 释放
} 

struct student *find(struct student *head, int n)  // 找到第n位同学的前一个同学
{
  struct student *p, *pold;
  pold = head;
  p = pold->next;
  int i = 0;
  while (i < n )
  {
    pold = p;
    p = p->next;
    i++;
  }
  
  return pold;
}