约瑟夫问题的传说:
著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
抽象出来问题分析与算法设计:
已知n个人(以编号1、2、3~~n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,他的下一个人又从1开始报数,数到m的那个人出列,依次规律重复下去,直到圆桌周围的人全部出列。
例如:n = 9, k = 1, m = 5
【解答】
出局人的顺序为5, 1, 7, 4, 3, 6, 9, 2, 8。
程序代码:
很明显这个问题用循环连接即可解决。
1 #include <iostream> 2 using namespace std; 3 4 //定义节点结构体 5 struct node{ 6 int data; 7 struct node *link; 8 }; 9 10 void Josephus(int n, int k, int m); 11 12 int main() 13 { 14 int n, k, m; 15 cout << "please input the parameters of Josehpus (n, k, m):"; 16 while(cin >> n >> k >> m) 17 { 18 Josephus(n, k, m); 19 cout << "please input the parameters of Josehpus (n, k, m):"; 20 } 21 return 0; 22 } 23 24 void Josephus(int n, int k, int m) 25 { 26 //定义头结点 27 cout << "creat the node: "; 28 node *current, *temp, *head; 29 temp = new node; 30 temp->data = 1; 31 temp->link = temp; 32 current = head = temp; 33 cout << temp->data << " "; 34 35 //建立循环链表 36 for(int i = 2; i <= n; ++i) 37 { 38 temp = new node; 39 temp->data = i; 40 temp->link = current->link; 41 current->link = temp; 42 current = temp; 43 cout << temp->data << " "; 44 } 45 node *previous = current; 46 current = head; 47 48 //是当前指针定位到第k个人 49 while(--k) 50 { 51 previous = current; 52 current = current->link; 53 } 54 55 cout << endl << "the list of deleting node:"; 56 57 while(n--) 58 { 59 //指针移动至第m个人 60 for(int i = 1; i < m; ++i) 61 { 62 previous = current; 63 current = current->link; 64 } 65 66 //删除操作 67 previous->link = current->link; 68 cout << current->data << " "; 69 delete current; 70 current = previous->link; 71 } 72 73 cout << endl; 74 }
运行结果:
已有很长一段时间没上博客园了,由于寝室有个同学天天和我炫耀他在博客园的排名节节高升,于是又激起了写技术博客的冲动,这是一个纯粹的平台,只有技术上的烦恼和困惑,但总能在上面找到答案。前几天帮一个大学的小师弟讲了个约瑟夫的问题,就当留作纪念吧!
来源:https://www.cnblogs.com/phquan/archive/2012/11/02/2751818.html