约瑟夫问题详解

  1. /*
  2. Name:   约瑟夫环 模拟
  3. Author: 李帅
  4. Date: 10-11-08 23:53
  5. Description: 
  6.           本程序模拟约瑟夫问题,自己写时参考了网上一些资料,我在此作了详细的注释。
  7.           约瑟夫问题: 一群人围成一圈,这群人共有 n个人,每个人身上都一个value,依次给这圈人编号:
  8. 1,2,n 一开始报数的上限值为m从第一个人(编号:1)自一开始报数报到m时停止报数,报到m的人出列,
    1. 将他的密码做为新的m值,从他的顺时针方向开始的下个人开始从新从一报数,如此下去,直至所有的人出列为止。 
  9. 这里输出出列顺序 
  10. */
  11. #include <iostream>
  12. using namespace std;
  13. //定义节点结构
  14. typedef struct Node
  15. {
  16.     int value;
  17.     int num;
  18.     Node *next;
  19. }Node;
  20. //定义总人数
  21. int n;
  22. //开始位置指针
  23. Node *FirstNode = NULL;
  24. //创建第一个循环链表,先创建一个,后面有用
  25. void CreateFirst(int);
  26. //删除节点p后面的节点
  27. void DeleteNode(Node*);
  28. int main()
  29. {
  30. //==========创建循环链表=============
  31. //读入总人数
  32.     cout << "总人数 n=";
  33.     cin >> n;
  34.     
  35. //用来读入人的value值
  36. int TempValue;
  37. //读入第一个人的value,用于 InitList 
  38.     cout << "num=1 value=";
  39.     cin >> TempValue;
  40.     
  41. //创建第一个循环链表,因为每次创建新节点都要和第一个节点相连,所以先创建第一个
  42. CreateFirst(TempValue);    
  43.     

int i;

  1. //定义临时变量,ToBeAdded用来创建新节点,current指向当前最后一个节点
  2.     Node *ToBeAdded,*current = FirstNode;      
  3.     for( i=2;i<=n;i++ )
  4.     {
  5.         ToBeAdded = new Node();
  6.         cout << "num=" << i << " value="
  7.         cin >> TempValue;
  8.         ToBeAdded->value = TempValue;
  9.         ToBeAdded->next = FirstNode;          //构成循环链表
  10.         current->next = ToBeAdded;            //连接新节点
  11.         ToBeAdded->num = i;
  12.         current = ToBeAdded;                  //current移到最新位置 
  13.     }
  14. Node *p = FirstNode;
  15. //========链表创建结束===========================
  16. //==========开始模拟运行=====================
  17.     current = FirstNode;
  18. Node *tem = current->next;
  19. Node *previous = tem;
  20. //把previous 放在tem前面
  21. while(tem!=current)
  22. {
  23.    previous = tem;
  24.    tem = tem->next;
  25. }
  26.     int m;
  27.     cout << "输入给定的m值:";
  28.     cin >> m;
  29.     
  30. i = 1;
  31.     int count = n;
  32.     
  33. //模拟整个过程
  34. while(i <= m)
  35. {
  36.    if(count==0)
  37.    {
  38.     cout << "所有人都已出列" << endl;
  39.     break;
  40.    }
  41.    if(i==m)//已循环m次,即数过m个人后
  42.    {
  43.     m = current->value;
  44.     i = 0;                   //重新对m赋予新的值,并对i初始化为0,后面加1,还是从1开始
  45.    
  46.     cout << current->num << endl; //输出删除节点number
  47.     DeleteNode(previous);    //注意,删除的是当前节点current
  48.    
  49.     count--;
  50.     current = previous;       //这里是为了防止后面previous = current;,而改变当前值
  51.    }
  52.    i++;
  53.    previous = current;
  54.    current = current->next;
  55. }
  56. system("pause");    
  57. return 0;
  58. void CreateFirst(int va) 
  59.     FirstNode = new Node();
  60.     FirstNode->num = 1;
  61.     FirstNode->value = va;
  62.     FirstNode->next = FirstNode;
  63. }       
  64. //删除节点p后面的节点,之所以不删除当前节点,是因为如果删除当前节点,就不方便将当前节点前后节点连接起来
  65. void DeleteNode(Node *p)
  66.     Node *tmp = p->next;
  67.     p->next = tmp->next;
  68.     delete tmp; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值