找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 4148|回复: 1

【C】约瑟夫环的双向链表解法

[复制链接]
发表于 2020-11-1 21:58:21 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
本帖最后由 new_starter 于 2020-11-1 22:01 编辑

约瑟夫环问题起源于一个犹太故事。
传说罗马人攻占了乔塔帕特,41个人藏在山洞中躲过了这场浩劫。这41人中包括历史学家Josephus约瑟夫和他的一个朋友。剩余的39人为了表示绝不屈服于罗马人于是决定集体自杀。所有这41人围成圈由第一个人开始顺时针报数,每报数为3的人就立刻自杀,然后再由下一个人重新开始报数,仍然是每报数为3的人就立刻自杀,直到所有人都死亡为止。
约瑟夫和他的朋友并不想自杀。于是约瑟夫想到了一个计策,他们两人同样参与到自杀方案中,但是最后却躲过了自杀。
下面的程序给出了约瑟夫环的解法,注意该程序需要StoneValley库的支持:
  1. #include <stdio.h>
  2. #include "../src/svstring.h"

  3. // Function: cbftvs_print_list
  4. // Desc:     Print item number in linked-list.
  5. // Param:    pitem: pointer to each node in a list. param: N/A.
  6. // Return:   CBF_CONTINUE only.
  7. int cbftvs_print_list(void * pitem, size_t param)
  8. {
  9.         printf("%ld, ", *(long *)((P_NODE_D)pitem)->pdata);
  10.         DWC4100(param);
  11.         return CBF_CONTINUE;
  12. }

  13. // Function: main
  14. // Desc:     Program entry.
  15. // Param:    N/A.
  16. // Return:   0: no error. 1: allocation failure.
  17. int main(void)
  18. {
  19.         char c;
  20.         long i, j;
  21.         LIST_D jring;
  22.         P_NODE_D pnew, pnode;
  23.         const char * sfx[] = { "m", "ms", "is", "are" };
  24.         strInitLinkedListDC(&jring);
  25.         pnode = jring;
  26.         printf("# A solution to Josephus's ring. <"); svPrintVersion(); printf("> #\n");
  27. Lbl_Start:
  28.         do
  29.         {
  30.                 printf("How many items will be there in a ring? ");
  31.                 scanf("%ld", &j);
  32.         }
  33.         while (j < 1);
  34.         for (i = 1; i <= j; ++i)
  35.         {
  36.                 if (NULL == (pnew = strCreateNodeD(&i, sizeof(long))))
  37.                 {
  38.                         puts("Error! Allocation failure while building ring.");
  39.                         strFreeLinkedListDC(&jring, FALSE);
  40.                         return 1; /* Allocation failure. */
  41.                 }
  42.                 if (NULL != pnode)
  43.                 {
  44.                         pnode->ppnode[NEXT] = pnew;
  45.                         pnew->ppnode[PREV] = pnode;
  46.                 }
  47.                 else
  48.                         jring = pnew;
  49.                 pnode = pnew;
  50.         }
  51.         /* Make a ring. */
  52.         pnode->ppnode[NEXT] = jring;
  53.         jring->ppnode[PREV] = pnode;
  54.         do
  55.         {
  56.                 printf("\tNow, there %s %ld ite%s in the ring.\nWhich number would you like \
  57. to choose to delete ite%s sequentially? ", sfx[(j > 1) + 2], j, sfx[j > 1], sfx[j > 1]);
  58.                 scanf("%ld", &i);
  59.         }
  60.         while (i < 1);
  61.         for ( ;; )
  62.         {
  63.                 pnode = strLocateItemDC_R(jring, i - 1);
  64.                 if (jring != pnode)
  65.                 {
  66.                         jring = pnode->ppnode[NEXT];
  67.                         strRemoveItemLinkedListDC(pnode);
  68.                         printf("\tRemove: %ld\n", *(long *)pnode->pdata);
  69.                         strDeleteNodeD(pnode);
  70.                 }
  71.                 else
  72.                         break;
  73.         }
  74.         if (NULL != pnode)
  75.         {
  76.                 printf("The rest of ite%s in the ring %s labeled with: ",
  77.                 sfx[jring != jring->ppnode[NEXT]], sfx[(jring != jring->ppnode[NEXT]) + 2]);
  78.                 strTraverseLinkedListDC_X(jring, NULL, cbftvs_print_list, 0, FALSE); puts("\b\b.");
  79.         }
  80.         strFreeLinkedListDC(&jring, FALSE);
  81.         pnode = NULL;
  82.         do
  83.         {
  84.                 fflush(stdin);
  85.                 printf("Would you like to continue playing(Y/n)? ");
  86.                 scanf("%c", &c);
  87.                 switch (c)
  88.                 {
  89.                 case 'Y': case 'y': goto Lbl_Start;
  90.                 case 'N': case 'n': return 0;
  91.                 }
  92.         }
  93.         while (c != 'Y' && c != 'y' && c != 'N' && c != 'n');
  94.         return 0;
  95. }
复制代码

程序运行结果如下:
Capture.PNG
该程序的核心是strLocateItemDC_R函数,使用该函数可以向前、向后定位循环双向链表上的任意一个节点。

本帖被以下淘专辑推荐:

回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-12-22 11:16 , Processed in 0.032737 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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