1、北京邮电大学信息与通信工程学院第 1 页数据结构实验报告实验名称: 实验一 约瑟夫问题学生姓名: *班 级: 20132111*班内序号: *学 号: 201321*日 期: 2014 年 1 月 4 日1 实验要求实验题目:利用循环链表实现约瑟夫问题的求解。约瑟夫问题如下:已知 n 个人(n=1)围坐一圆桌周围,从 1 开始顺序编号。从序号为 1 的人开始报数,顺时针数到 m 的那个人出列;他的下一个人又从 1 开始报数,数到 m 的那个人又出列;依此规则重复下去,直到所有人全部出列。请问最后一个出列的人的编号。实验目的:熟悉 C+语言的基本编程方法,掌握集成编译环境的调试方法学习指针、模板
2、类、异常处理的使用掌握线性表的操作的实现方法学习使用线性表解决实际问题的能力2. 程序分析2.1 存储结构采用单循环链表实现约瑟夫问题的求解单循环链表示意图2.2 关键算法分析1、关键算法首先通过尾插法建立单循环链表,若只有一个人,即只删除该人即可,若多于一北京邮电大学信息与通信工程学院第 2 页人,则每查到 m 个人时删除该节点,并将循环链表连接好,共循环 n-1 次,每次删除均返回被删数值。2、代码详细分析:1).指针结构、类的声明struct Node /创立节点 int number; Node *next; ; class Joseph /建立 Joseph 类 private: i
3、nt n; int m; Node *front ; /front 头指针public: Joseph(int nn, int mm); /构造函数 Joseph(); /析构函数void Delete(); /删除函数; 2).单循环链表的建立Joseph:Joseph(int nn, int mm) /构造函数,建立循环链表 n=nn; m=mm; Node *p,*rear; /建立两个指针.尾插法,p2 始终指向为节点for(int i=1; inumber=i; if(i=1) /建立空链表 front=p; rear=p; else rear-next=p; rear=p; rea
4、r-next=front; /尾指向头,循环完成 算法:北京邮电大学信息与通信工程学院第 3 页 设两个指针 p,rear, rear 为尾节点, p 为新增加的节点 若是空链表,则 front=p; rear=p; 否则用尾插法,即 p 在 rear 的后面,将 p 给 rear;rear-next=p; rear=p; 头结点赋给 rear 的指针域,完成循环循环次数为 n, 时间复杂度为 O(n)3). 输入值异常的情况coutn;if (nm;if (mnext; /p1 向后移count+; coutnumbernext=p1-next; p1=p1-next; /p1 后移,防止删
5、除后指针悬挂delete p; 北京邮电大学信息与通信工程学院第 4 页 coutnumbernext; p2 始终指向第一个节点 摘链,将 p 指向待删除的 p1,即将 p1 元素从链表中摘除: 输出 p1 的数值 释放 p 元素:delete p;循环次数为 m(n-1), 时间复杂度为 O(n)5)析构函数Joseph:Joseph() /析构函数 delete front; front=NULL; 6)主函数void main() int n,m; coutn; coutm;Joseph joseph(n,m); joseph.Delete(); 3. 程序运行结果测试主函数流程: 北京邮电大学信息与通信工程学院第 5 页是是流程图示意图1、 测试条件:n 数量级无限制 2、 测试结论开始等待用户输入输入值是否有效查找删除节点循环次数是否大于 n-1 次输出最后一个数值结束北京邮电大学信息与通信工程学院第 6 页4. 总结由于是第一次做数据结构的实验,而上学期的 C+也因长时间没有碰过而稍显手生,在码程序的过程中遇到了很多问题,但通过翻看教材已基本解决。约瑟夫虽然构思起来比较简单,但实际执行时经常出现各种意想不到的问题,如输出次数不对等等,通过将近两天的调试才终于完成,很有成就感。接下来如果有时间可以在原程序中加入其实位置编号,使得起始位置也可由用户自定。