约瑟夫问题

2019-09-01 19:34

利用循环链表实现约瑟夫问题的求解。

约瑟夫问题如下:有n个人(n>=1)围坐在一个圆桌周围,把这n个人依次编号为1,…,n。从编号是1的人开始报数,顺时针数到m的那个人出列,他的下一个然后从出列的下一个人重新开始报数,数到第m个人又出列,…,如此反复直到所有的人全部出列。请问最后一个出列的人的编号。

2. 程序分析

对于这个程序来说,首先要确定构造链表时所用的插入方法。当数到m时一个人就出列,也即删除这个节点,同时建立这个节点的前节点与后节点的联系。由于是循环计数,所以才采用循环列表这个线性表方式。

在这个程序中解决了存储问题后,之后最大的难点就是关于出列节点的逻辑判断。由于我插入元素时是将rear指针中也存入了元素值,又增加了一个front指针,实际上是front指针始终存在而rear指针有可能消除。这样遇到的问题就是,假设p本身就是rear指针,那当移到下一位时就应该移动两位来跳过front这一个空节点。这个是程序实现中容易发生逻辑错误的地方。

2.1 存储结构

本实验中所用的存储结构为单链表。 以下即为单链表的存储结构示意图:

front

(1) 空单循环链表 a1 a2 … an front rear (2)非空单循环链表

2.2 关键算法分析

1、 关键算法:

(1)、插入:在把元素插入到循环链表中时,由于是采用的头插法,所以我保留了front头结点。在每加入一个节点时,都会直接连接在front后面,从而保证一开始就赋值的rear尾节点不用修改。

伪代码阐释如下:

1)、在堆中建立新节点:Node *s=new Node; 2)、将a[i]写入到新节点的数据域:s->data=a[i]; 3)、修改新节点的指针域:s->next=front->next;

4)、修改头结点的指针域,将新节点加入到链表中:front->next=s;

时间复杂度为:1;

(2)、删除:首先通过p指针查找到所要删除的节点的前一个节点,继而通过q=p->next简单地删除掉。假设所要查找的为第i个元素。

伪代码阐释如下: 1)、在堆中建立新节点p,通过循环查找到i-1,将此节点的地址赋给p。 2)、设q指向第i个节点:若p=rear,则q=front->next; 否则,q=p->next;

3)、摘链,即将q从链表中摘除:若q=rear,则p->next=front->next;否则,则p-next=q->next.

4)、保存q元素的数据:x=q->data; 5)、释放q元素:delete q;

时间复杂度为:1; (3)、约瑟夫问题的基本思想:在这个循环查找问题中,通过循环链表实现了循环查找到节点。一个关键部分就是删除节点后进行链表的链接,从而保证链表的循环性。在查找方面上,我利用了一个for循环来计数所查找过的节点。 其中查找的时间复杂度也为1;


约瑟夫问题.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:《项目建设资金支付管理办法》

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: