约瑟夫环问题(武汉理工2018计算机复试题之一)

复试题仅仅把约瑟夫环问题中的固定报数改成出列人的序号,这里就按照约瑟夫环问题解决。

问题描述:有n个人围坐在一起,编号为1~n,现在从第k个人开始报数,报到m时。该人出列,并且从下一个人开始重新报数。报到m继续出列…这样下去 最后一个出列的人序号时多少?

算法思想:这样的问题,用单循环链表再合适不过了。结束条件就是p->next = p,此时p就是最后一个出列的结点。 这道题应该算是纯数据结构里的问题。

代码如下:

#include 

using namespcae std;

typedef struct Node
{
 int ID;  //编号
 struct Node *next;   //
}Node,*PNode;

PNode CreateJoseffList(int n)  //创建约瑟夫环,返回编号为1的节点地址
{
 PNode tmp = new Node;
 tmp->ID = 1;
 tmp->next = NULL;
 PNode first = tmp;
 for (int i = 2;i <= n;i++)
 {
  PNode pnode = new Node;
  pnode->ID = i;
  tmp->next = pnode;
  tmp = pnode;
 }
 tmp->next = first; //最后一个节点指向第一个节点,围成圈
 return first;
}

int BeginCount(PNode p, int k, int m)  //第k个人开始,每报到m出列
{
 PNode tmp = p;
 for (int i = 1;i < k;i++)
 {
  tmp = tmp->next;
 }
 while (tmp->next!=tmp) //如果tmp->next = tmp 说明tmp就是最后一个元素了
 {
  for (int j = 1;j < m - 1;j++) //找到报数为m-1的点,即前驱节点
   tmp = tmp->next;
  PNode q = tmp->next;
  tmp->next = tmp->next->next;
  free(q);  //删除报数为m的节点
  tmp = tmp->next;
 }
 return tmp->ID;
}

int main()
{
 int n, k, m; //第k个人开始,报到m出列
 cin >> n >> k >> m;
 PNode first = CreateJoseffList(n);
 int result = BeginCount(first, k, m);
 cout << result;
    
}
//代码并不难想,属于送分题,但是考试时时间不多,只有熟能生巧才能游刃有余。


你可能感兴趣的:(学习c++,约瑟夫环问题,武汉理工计算机复试,单循环链表)