1、八、主要参考资料 11一、设计任务与要求1.1 总体目标与任务要求 总体目标:用C+软件设计一个程序用来求出一个序列的出列顺序。 要求:利用单向循环链表存储结构实现这个过程,按照出列的顺序输出每一个人的编号。1.2 题目选择与目的意义 据说joseph在战争时期,与39个犹太人和他一个朋友躲到一个洞里,39个犹太人决定宁死也不被敌人抓到,于是他们决定了一个自杀方式,41个人排成圈,由第一个人开始报数,每报到三的人就必须自杀,依次循环直到每个人都自杀身亡。但josrph和他的朋友并不想村从,于是他把自己和朋友安排到第16个位置和第31个位置,于是他们俩逃过了这个死亡游戏。 Joseph问题是个很
2、由意思的问题,其意义在于它启发我们用一个循环的链来表示这个圈子,可以使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人的标记。所以我们选择了这个题目。1.3 所选题目的主要工作 以单向循环链表的方式建立约瑟夫环。建立输入处理输入数据,输入m的初值,n ,建立单向链表,输入每个人的密码建立一个输出函数,将正确的出列顺序输出序列。二、需求分析2.1 用户需求分析编号是1,2,,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列
3、,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。设计一个程序来求出出列顺序。2.2 功能需求分析 各个模块间的调用关系如下: 2.3 系统需求分析 系统软件:Windows操作系统 开发软件:Microsoft Visual C+ 6.0 其他软件:Microsoft Office Word 2003,Adobe Photoshop CS3三、概要设计3.1 各模块的算法设计说明 函数流程图:joseph *creat(void),void game(joseph *head,int m),void main()部分函数流程图:3.2 存
4、储结构设计说明typedef struct Node ElemType date; /编号 int mima; /密码 struct Node *next; Node,*LinkList; 单向循环链表:LinkList H; /表头指针Node *Q,*Pre;/*Q指新建结点,*pre指向当前工作结点Q=(Node*)malloc(sizeof(Node);构造函数:void InitList(LinkList *H); /初始化循环链表void InPut(LinkList H,int *A);/插入结点void DelList(LinkList H,int *x, int*a); /删
5、除结点四、详细设计typedef struct Lnode/节点类型ElemType data;Struct Lnode *next;*Link,*Position;typedef struct /链表类型Link head,tail; /分别指向线性链表中的头结点和最后一个结点Int len; /只是线性链表中的数据元素LinkList;Status MakeNode(Link&p,ElemType e);/分配由p指向的值为e的结点,并返回OK;若分配失败,则返回ERRORvoid FreeNode(Link&p);/释放p所指接点Status InitList(LinkList&L);
6、/构造一个空的线性表L Status DestroyList(LinkList&/销毁线性表L,L不再存在Status ClearList(LinkList& /将线性表L从之唯恐表,并释放原链表的结点空间Status InsFirst(Link h,Link s); /已知h指向线性链表的头结点,将s所直接点插入在第一个结点之前Status DelFirst(Link h,Link&q); /已知h指向线性表的头结点,删除链表中的第一个结点并以q返回Status Append(LinkList&L,Link s);/将指针s所指(彼此以指针项链)的一串结点链接在线性链表L的最后一个结点/之后
7、,并改变链表L的尾指针指向新的尾节点Status Remove(LinkList&L,Link& /删除线性链表L中的尾结点并以q返回,改变链表L的尾指针只想新的尾结点Status InsBefore(LinkLIst&p,Link s);/已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,/并修改指针p指向新插入的结点Status InsAfter (LinkLIst&/已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,Status SetCurElem(Link&/已知p指向线性链表中的一个结点,用e更新p所指结点中的数据元素的值ElemType Get
8、CurElem(Link p);/已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值Status listEmpty(LinkList L);/若线性链表L为空表,则返回TRUE,否则返回FALSEint ListLength(LinkList L);/返回线性链表L中元素个数Position GetHead(LinkList L); /返回线性链表L中头结点的位置Position GetLast(LinkList L); /返回线性链表L中最后一个结点的位置Position PriorPos (LinkList L,Link p);/已知p指向线性链表L中的一个结点,返回p所指结点
9、的直接前驱的位置/若无前驱,则返回NULLPosition NextPos(LinkList L,Link p);/已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置/若无后继,则返回NULLStatus LocatePos(LinkList L,int I,Link& /返回p指示线性链表L中的第I个节点的位置并返回OK,i值不合法时返回ERRORPosition LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType);/返回线性链表L中的第1个与e满足函数compare()判定关系的元素的位置,
10、/若不存在这样的元素,则返回NULLStatus ListTraverse(LinkList L,status(*visit)();/依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败 五、源代码#includestdio.hmalloc.hstdlib.h#include typedef struct ajose int num; int code;joseph; struct ajose *next;joseph *creat(void) joseph *head,*p1,*p2; int i=0,code; head=(joseph *)malloc(sizeo
11、f(joseph); p2=p1=(joseph *)malloc(sizeof(joseph); head-next=NULL; cout请输入第i+1num=i;code=code; if(i=1) head-next=p1; else p2- p2=p1; coutnext=head-next; printf(建立成功!n); return head; void game(joseph *head,int m) joseph *p1,*p2; int i=1; p2=head; p1=head- while(head-num1) if(i=m) next=p1- m=p1-code; i
12、=1; printf(%3d,p1-num); free(p1); p1=p2- /p1指向输出结点 num-; continue; i+; p2=p1; p1=p1- /将p1指针指向所要输出的结点的前一结点 return ; void main() joseph *head; int m; head=creat(); printf(请输入m的值 m:m); game(head,m); getch();njoseph环 单向循环链表结束n 六、运行结果分析由于刚开始忽略了该链表没有头结点这样一个特殊性,没有把第一个结点单独拿出来建立,因而出现了一些逻辑上的错误程序写完后发现所有基本操作的结果
13、均不能够返回到主函数,后通过XX百科和以前的C教材知道要用传址的方式调用,但是具体实现起来还是耗费了不少的时间算法的时空分析该程序不占用额外空间,因此空间复杂度是O(n)的,基本操作中,Destroy操作是O(n)的,Next_m操作是O(m)的,其余的操作都是O(1)的,整个程序的时间复杂度是O(n*m)的七、收获与体会 通过学习和实践,使我明白在进行面向过程的程序设计时,一般首先考虑程序所要实现的功能,然后设计为实现这些功能所必须采取的步骤,这些步骤就是过程。如果一个过程比较复杂而不能直接使用已有的抽象进行实现,则对这个过程进行分解,使分解之后的每一步(更低级的过程)能够直接对应着一条语句
14、。通过将分解之后的一系列过程封装在一个函数抽象中,程序员在特定的时刻只关心有限的细节,这个新的函数抽象比其较低级的抽象更接近问题求解的过程,因而,能够很好地映射问题求解中的过程。如果这个过程出现在许多问题求解中,那么,这个函数抽象就可能被重复利用。由于是第一次用“以数据结构为中心”的思想编程,所以并不是很习惯,在主函数中还是充斥着很多基本语句,以后仍要多多练习。八、主要参考资料1James P.Cohoon & Jack W.Davidson.C+程序设计.电子工业出版社2严蔚敏.数据结构(C语言版).清华大学出版社3姚云鸿.程序设计与数据结构.清华大学出版社指导教师签字: 年 月 日 #in
15、clude using namespace std;typedef struct CirListint num,pwd;struct CirList *next;CirList,*LCirList;int main()int m,n; /max为报数上限,num为人数。int i,j;Please enter n=n);Please enter m= LCirList head,tail,p,q; /head为头节点指针,tail为尾节点指针,p为当前指针的前一指针,q为当前指针。 head = (CirList*)malloc(sizeof(CirList); p = head; for(i = 1; i next = q; p = q; tail = q; tail-next = head; /建立num个节点的循环链表。= n;num = i;Please enter No.%ds password:,i);(p-pwd); p = p- /输入密码。result: p = tail; for(i =1;=n; for(j = 1; j m = q-pwd; %d,q-next = q- /删除元素 free(q); /输出编号。 return 0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1