六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 134|回复: 0

单循环链表解决约瑟夫环问题

[复制链接]

升级  40%

4

主题

4

主题

4

主题

童生

Rank: 1

积分
20
 楼主| 发表于 2013-2-5 02:17:10 | 显示全部楼层 |阅读模式
     这几天为了准备笔试忙着复习C语言,决定把当时学C时的一些经典问题再温习一下,当时啊,学的稀里糊涂的,呵呵,现在回头来仔细写一写代码,就算是纪念当时的个性十足的赵老师了吧!
    约瑟夫问题的:编号为1,2,....,N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的M值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。
     解决思路还是很简单的,主要是要会熟练运用单循环链表的数据结构,通过单循环链表模拟围坐的一圈人,然后根据相应的密码进行报数,然后删除相应的链表节点。下面是C代码:
<div class="dp-highlighter"><div class="bar">
       
  • #include <stdio.h>       
  •  #include <stdlib.h>       
  •  #define MAX_NODE_NUM 100       
  •  #define TRUE 1U       
  •  #define FALSE 0U       
  •      
  •  typedef struct NodeType       
  •  {       
  •       int id;       
  •       int cipher;        
  •            struct NodeType *next;       
  •  } NodeType;       
  •      
  •  /* 创建单向循环链表 */       
  •  static void CreaList(NodeType **, const int);       
  •  /* 运行"约瑟夫环"问题 */       
  •  static void StatGame(NodeType **, int);       
  •  /* 打印循环链表 */       
  •  static void PrntList(const NodeType *);       
  •  /* 得到一个结点 */       
  •  static NodeType *GetNode(const int, const int);       
  •  /* 测试链表是否为空, 空为TRUE,非空为FALSE */       
  •  static unsigned EmptyList(const NodeType *);       
  •      
  •  int main(void)       
  •  {       
  •        int n, m;       
  •             NodeType *pHead = NULL;       
  •             while (1)       
  •             {       
  •                 printf("请输入人数n(最多%d个): ", MAX_NODE_NUM);       
  •                 scanf("%d", &n);       
  •                 printf("和初始密码m: ");       
  •                 scanf("%d", &m);       
  •                 if (n > MAX_NODE_NUM)       
  •                 {       
  •                     printf("人数太多,请重新输入!\n");       
  •                     continue;       
  •                 }       
  •                 else       
  •                     break;       
  •             }       
  •             CreaList(&pHead, n);       
  •             printf("\n------------ 循环链表原始打印 -------------\n");       
  •             PrntList(pHead);       
  •             printf("\n-------------删除出队情况打印 -------------\n");       
  •             StatGame(&pHead, m);       
  • }       
  •      
  •  static void CreaList(NodeType **ppHead, const int n)       
  •  {       
  •             int i, iCipher;       
  •             NodeType *pNew, *pCur;       
  •             for (i = 1; i <= n; i++)       
  •             {       
  •                 printf("输入第%d个人的密码: ", i);       
  •                 scanf("%d", &iCipher);       
  •                 pNew = GetNode(i, iCipher);       
  •                 if (*ppHead == NULL)       
  •                 {       
  •                     *ppHead = pCur = pNew;       
  •                     pCur->next = *ppHead;       
  •                 }       
  •                 else       
  •                 {       
  •                     pNew->next = pCur->next;       
  •                     pCur->next = pNew;       
  •                     pCur = pNew;       
  •                 }       
  •             }       
  •             printf("完成单向循环链表的创建!\n");       
  • }       
  •      
  • static void StatGame(NodeType **ppHead, int iCipher)       
  • {       
  •             int iCounter, iFlag = 1;       
  •             NodeType *pPrv, *pCur, *pDel;       
  •             pPrv = pCur = *ppHead;       
  •             /* 将pPrv初始为指向尾结点,为删除作好准备 */       
  •             while (pPrv->next != *ppHead)       
  •                 pPrv = pPrv->next;       
  •             while (iFlag)       
  •             {        
  •                 for (iCounter = 1; iCounter < iCipher; iCounter++)       
  •                 {       
  •                     pPrv = pCur;       
  •                     pCur = pCur->next;       
  •                 }       
  •                 if (pPrv == pCur)       
  •                     iFlag = 0;       
  •                 pDel = pCur; /* 删除pCur指向的结点,即有人出列 */       
  •                 pPrv->next = pCur->next;       
  •                 pCur = pCur->next;       
  •                 iCipher = pDel->cipher;       
  •                 printf("第%d个人出列, 密码: %d\n", pDel->id, pDel->cipher);       
  •                 free(pDel);       
  •             }        
  •             *ppHead = NULL;        
  •             getchar();      
  • }       
  •      
  • static void PrntList(const NodeType *pHead)       
  • {       
  •             const NodeType *pCur = pHead;       
  •             if (EmptyList(pHead))       
  •                 return;       
  •             do       
  •             {       
  •                 printf("第%d个人, 密码: %d\n", pCur->id, pCur->cipher);       
  •                 pCur = pCur->next;       
  •             } while (pCur != pHead);       
  •             getchar();      
  • }       
  •      
  • static NodeType *GetNode(const int iId, const int iCipher)       
  • {       
  •             NodeType *pNew;       
  •             pNew = (NodeType *)malloc(sizeof(NodeType));       
  •             if(!pNew)       
  •             {       
  •                 printf("Error, the memory is not enough!\n");       
  •                 exit(-1);       
  •             }       
  •             pNew->id = iId;       
  •             pNew->cipher = iCipher;       
  •             pNew->next = NULL;       
  •             return pNew;       
  • }       
  •      
  • static unsigned EmptyList(const NodeType *pHead)       
  • {       
  •             if(!pHead)       
  •             {       
  •                 printf("The list is empty!\n");       
  •                 return TRUE;       
  •             }       
  •             return FALSE;       
  • }  
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表