【练习】双向链表应用于约瑟夫问题
2018-01-22 21:09
176 查看
约瑟夫问题:有n个小朋友,编号分别为1,2,…,n,按照编号围成一个圆圈,他们按顺时针方向从编号为k的人由1开始报数,报数为m的人出列,他的下一个人重新从1开始报数,数到m的人出列, 照这样重复下去,直到所有的人都出列。编写一个算法,输入n,k和m,按照出列顺序输出编号。
分析:第一步创建一个具有n个结点的不带头结点的双向循环链表,编号从1到n,代表n个小朋友;第二步找到第k个结点,即第一个开始报数的人;第三步编号为k的人从1开始报数,并开始计数,报到m的人出列即将该结点删除。继续从下一个结点开始报数,直到最后一个结点被删除。
类型定义
函数文件
主程序
测试结果
分析:第一步创建一个具有n个结点的不带头结点的双向循环链表,编号从1到n,代表n个小朋友;第二步找到第k个结点,即第一个开始报数的人;第三步编号为k的人从1开始报数,并开始计数,报到m的人出列即将该结点删除。继续从下一个结点开始报数,直到最后一个结点被删除。
类型定义
#include<stdio.h> #include<malloc.h> #include<stdlib.h> /*双向链表类型定义*/ typedef int DataType; typedef struct Node { DataType data; struct Node *prior; struct Node *next; }DListNode,*DLinkList; /*函数声明*/
函数文件
void Josephus(DLinkList head,int n,int m,int k) /*在长度为n的双向循环链表中,从第k个人开始报数,数到m的人出列*/ { DListNode *p,*q; int i; p=head; for(i=1;i<k;i++) /*从第k个人开始报数*/ { q=p; p=p->next; } while(p->next!=p) { for(i=1;i<m;i++) /*数到m的人出列*/ { q=p; p=p->next; } q->next=p->next; /*将p指向的结点删除,即报数为m的人出列*/ p->next->prior=q; printf("%4d",p->data);/*输出被删除的结点*/ free(p); p=q->next; /*p指向下一个结点,重新开始报数*/ } printf("%4d\n",p->data); } DLinkList CreateDCList(int n) /*创建双向循环链表*/ { DLinkList head=NULL; DListNode *s,*q; int i; for(i=1;i<=n;i++) { s=(DListNode*)malloc(sizeof(DListNode)); s->data=i; s->next=NULL; /*将新生成的结点插入到双向循环链表*/ if(head==NULL) { head=s; s->prior=head; s->next=head; } else { s->next=q->next; q->next=s; s->prior=q; head->prior=s; } q=s; /*q始终指向链表得最后一个结点*/ } return head; }
主程序
void main() { DLinkList h; int n,k,m; printf("输入环中人的个数n="); scanf("%d",&n); printf("输入开始报数的序号k="); scanf("%d",&k); printf("报数为m的人出列m="); scanf("%d",&m); h=CreateDCList(n); Josephus(h,n,m,k); }
测试结果
相关文章推荐
- C语言通过双向循环链表解决Josephus(约瑟夫)问题
- 约瑟夫问题 java解法(双向链表解决)
- php实现单,双向链表,环形链表解决约瑟夫问题
- 循环双向链表 及 约瑟夫问题的解决
- 约瑟夫问题---list双向链表
- 约瑟夫问题循环链表解法、队列解法
- 环形链表+约瑟夫问题实现
- 数据结构 循环链表之约瑟夫问题
- 使用单向循环链表实现约瑟夫问题
- 约瑟夫解决问题的循环链表
- 约瑟夫问题——链表实现
- 采用循环链表结构求解约瑟夫问题
- 单循环链表的约瑟夫问题(C++)
- 链表I 约瑟夫问题(删除+计数!典题)
- Have Fun with Numbers及循环链表(约瑟夫问题)
- 约瑟夫问题(单循环链表解决)
- 约瑟夫问题--双向循环链表的创建与删除
- 用单循环链表实现约瑟夫问题。
- 练习系列 - 1、把二元查找树转变成排序的双向链表
- 约瑟夫问题的单向循环链表的解法