循环链表求解约瑟夫问题
来源:互联网 发布:技术军官知乎 编辑:程序博客网 时间:2024/05/16 09:11
题目描述
有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。
输入
初始人数n
输出
最后一人的初始编号
样例输入
3
样例输出
2
此题为约瑟夫问题,最直接的办法就是采用循环链表求解。
代码如下:
#include<iostream>using namespace std;/**附加头结点的循环链表的类定义:*作为私有数据成员,在链表的类定义中封装了2个链接指针:first、last,分别指示链表的附加头结点和链尾节点。*/template <class T>struct CircLinkNode //链表结点类的定义{ T data; //数据域 CircLinkNode<T> *link; //链指针域 CircLinkNode(CircLinkNode<T> *next = NULL):link(next) {} //仅初始化指针成员的构造函数 CircLinkNode(T d,CircLinkNode<T> *next = NULL):data(d),link(next) {} //初始化数据与指针成员的构造函数};template <class T>class CircList //链表结点类定义{public: CircList() //构造函数,创建附加的头结点 { first = last = new CircLinkNode<T>; first->link = first; } CircList(CircList<T> &L); //复制构造函数 CircLinkNode<T> *getHead()const //返回附加头结点的地址 { return first; } CircLinkNode<T> *getEnd()const //返回附加尾结点的地址 { return last; } void setEnd(CircLinkNode<T> *p) //设置尾指针的位置 { last = p; } CircLinkNode<T> *Locate(int i); //搜索第i个元素的值 bool Insert(int i,T x); //在第i个元素后插入xprotected: CircLinkNode<T> *first,*last; //头指针,尾指针};template <class T>CircLinkNode<T> *CircList<T>::Locate(int i){ if(i < 0) return NULL; CircLinkNode<T> *current = first; int k = 0; while(current->link != first && k < i) { current = current->link; k++; } return current;}template <class T>bool CircList<T>::Insert(int i,T x){ if(i < 0) return false; CircLinkNode<T> *p = Locate(i); CircLinkNode<T> *newNode = new CircLinkNode<T>(x); newNode->link = p->link; p->link = newNode; if(p == last) //如果插入的结点是在尾结点后,需要修改尾指针 last = newNode; return true;}template <class T>CircList<T>::CircList(CircList<T> &L){ T value; CircLinkNode<T> *srcptr = L.getHead(); CircLinkNode<T> *destptr = first = new CircLinkNode<T>; while(srcptr->link != first) { value = srcptr->link->data; destptr->link = new CircLinkNode<T>(value); destptr = destptr->link; srcptr = srcptr->link; } last = destptr;}/**函数Josephus用于选择,其参数包括人数值n和报数值m。该函数过程共执行n-1趟报数循环,每趟连续*计数m项,并从链表中删除第m个节点及打印该节点的编号,当只剩下一个结点时跳出循环,结束算法。*/template <class T>void Josephus(CircList<T> &Js,int n,int m){ CircLinkNode<T> *p = Js.Locate(1),*pre = NULL; int i,j; for(i = 0; i < n-1; i++) { for(j = 1; j < m; j++) { pre = p; p = p->link; if(p == Js.getHead()) //需要跳过附加头结点 { pre = p; p = p->link; } } // cout<<"出列的人是"<<p->data<<endl; if(pre->link == Js.getEnd()) //删去尾指针所指的结点需要修改尾指针 Js.setEnd(pre); pre->link = p->link; delete p; p = pre->link; if(p == Js.getHead()) //需要跳过附加头结点 { pre = p; p = pre->link; } }}int main(){ CircList<int> clist; int i,n; cin>>n; for(i = 1; i <= n; i++) clist.Insert(i,i); //形成约瑟夫环 Josephus(clist,n,3); //解决约瑟夫问题 cout<<clist.getEnd()->data; //尾指针必定指向最后一个结点 return 0;}
参考文献
[1] 殷人昆编著. 数据结构——用面向对象方法与C++语言描述. 北京:清华大学出版社,2007.
0 0
- 用循环链表求解约瑟夫问题
- 循环链表求解约瑟夫问题
- 利用循环链表实现约瑟夫问题的求解
- 数据结构:循环链表求解约瑟夫环问题
- 循环链表示例:求解约瑟夫问题
- 单向循环链表求解约瑟夫环
- C语言循环链表求解约瑟夫环问题(循环方式)
- 循环链表示例:求解约瑟夫问题(C++实现)
- 利用循环链队列求解约瑟夫环问题(…
- 约瑟夫(Josephus)问题的求解——利用循环链表
- 约瑟夫问题-循环链表
- 循环链表:约瑟夫问题
- 循环链表-约瑟夫问题
- 循环链表--约瑟夫问题
- 使用循环双链表求解约瑟夫环问题
- 约瑟夫问题(循环单链表求解)
- 循环链表与约瑟夫问题
- 单向循环链表实现约瑟夫问题
- 简述对http协议的理解
- Map遍历的四种方法
- 纯lua实现MD5
- Unity 消息发送机制 解析
- NS3 Tutorial:第五章 Tweaking
- 循环链表求解约瑟夫问题
- http
- [远程桌面]程mstsc连接Windows Server2008 未安装任何音频输出设备 启用声音音频解决
- Android -- Wifi连接流程分析
- 聊聊淘宝天猫个性化推荐技术演进史
- Android广播的发送与接收
- JSP数据交互
- 闭包的7种形式
- jsp 内置对象response,request,session 以及 cookie 对象的综合例子 和 include指令