数据结构课程设计 约瑟夫环(试题学习)
题目:约瑟夫环问题
数据结构上机实验报告02090401 12 雒文杰题目:约瑟夫环问题一.问题描述设有n个人围做一圈,现从某个人开始报数,数到m的人出列,接着从出列的下一个人开始重新报数,数到m的人又出列,如此下去,直到所有人都出列为止。
试设计确定他们的出列次序序列的程序。
二.基本要求运用循环单链表解决约瑟夫环问题。
三.算法说明本程序采用循环单链表的算法来解决约瑟夫环问题:建立一个循环单链表,按顺序查找指定结点,找到后删除,最后打印删除的编号序列。
四.源程序清单#include <stdio.h>#include <malloc.h>#define n 7#define NULL 0struct clist{int data,order; /* 人的序号, 密码*/struct clist *next; /* 指向下一个节点的指针*/};typedef struct clist cnode;typedef cnode *clink;clink createclist(int *array,int len) /* 建立循环链表*/{clink head;clink before;clink new_node;int i;head=(clink)malloc(sizeof(cnode));if(!head)return NULL;head->data=array[0];head->order=1;head->next=NULL;before=head;for(i=1;i<len;i++){new_node=(clink)malloc(sizeof(cnode)); if(!new_node)return NULL;new_node->data=array[i];new_node->order=i+1;new_node->next=NULL;before->next=new_node;before=new_node;}new_node->next=head;return head;}void main(){clink head,ptr;int find,j,i,a,list[n];printf("Please input 'm'\n");for(i=0;i<n;i++){scanf("%d",&list[i]);printf("\n");}head=createclist(list,n);printf("input first 's'\n");scanf("%d",&a);for(i=1;i<a-1;i++)head=head->next;ptr=head->next;head->next=ptr->next;find=ptr->data;printf("order is %d\n",ptr->order);free(ptr);for(j=1;j<n;j++){for(i=1;i<find;i++)head=head->next;ptr=head->next;head->next=ptr->next;find=ptr->data;printf("order is %d\n",ptr->order);free(ptr); /* 让最后一个人也出列*/ }}。
数据结构课程设计 约瑟夫环问题(报告+代码)
学院计算机与信息工程系数据结构课程设计设计题目:约瑟夫环问题专业班级学号姓名指导教师2010年12月20日约瑟夫环一.实验目的:本实验是设计一个可以解决约瑟夫环问题的程序。
此程序要求利用单向循环链表存储结构模拟此过程,按照出列的顺序印出个人的编号。
二.实验环境:VC2008.三.试验步骤:1.问题分析和任务定义本实验要求设计一个程序解决约瑟夫环问题,且要利用单向循环链表存储结构模拟此过程。
这就要求我们必须用链表结构而不能用像数组等其它结构。
首先输入的数据必须是整型且是整数,同样输出的也必须是整型且整数;其次也要备好测试数据(包括合法的输入数据和非法形式输入的数据)以此来检查程序是否符合要求;最后2.数据类型和系统设计链表存储结构的定义:typedef struct Node{}SeqList链表的建立:SeqList * Creat(int num){}链表的输出:void OutQueue(SeqList * tail, int num, int code){}3.详细设计:#include <stdio.h>#include <stdlib.h>typedef struct Node{int num;int code;struct Node * next;}SeqList;SeqList * Creat(int);void OutQueue(SeqList *, int , int );int main(){int n,m,i;printf( " 姓名:徐正杰学号:090502201:\n");printf("Input The Number of People, Frist Code:");{int num = 0,code = 0;scanf("%d%d",&num, &code);{SeqList * tail = NULL;tail=Creat(num);OutQueue(tail, num, code);}}return 0;}SeqList * Creat(int num){getchar();SeqList * tail = NULL;tail=(SeqList *)malloc(sizeof(SeqList));{int i = 1, code = 0;printf("Input Num.%d Code:", i);scanf("%d", &code);tail->num = i;tail->code = code;tail->next = tail;{SeqList * p = NULL;for(i = 2; i <= num; ++i){p = (SeqList *)malloc(sizeof(SeqList));if(p){printf("Input Num.%d Code:", i);scanf("%d", &code);p->num = i;p->code = code;p->next = tail->next;tail->next = p;tail = p;}else{perror("Out of menroy!");getchar();exit(1);}}}}return(tail);}void OutQueue(SeqList * tail, int num, int code) {printf("Out of Queue:");{SeqList * p;while(tail - tail->next){code=(code-1)%num+1;{int i;for(i = 1; i < code; ++i){tail = tail->next;}}p = tail->next;printf("%d,", p->num);tail->next = p->next;code = p->code;free(p);p = NULL;--num;}}printf("%d.",tail->num);free(tail);tail = NULL;}4.调试分析在本次试验调试中很不顺利。
大学数据结构课程设计-实习报告——约瑟夫环
20XX年复习资料大学复习资料专业:班级:科目老师:日期:数据结构实习报告题目:程序求解约瑟夫环问题出列顺序一、需求分析1.以单项循环链表存储结构模拟约瑟夫环问题。
即编号为1、2、3…、n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。
按出列顺序印出各人的编号。
2.演示程序以用户与计算机的对话方式执行,用户输入相应的数据,输出结果显示在其后。
3.测试数据:(1)n=77个人的密码依次为:3,1,7,2,4,8,4;首先m值为6(正确的输出顺序为:6,1,4,7,2,3,5)(2)n=55个人的密码依次为:1,2,3,4,5首先m值为1(正确的输出顺序为:1,2,4,3,5)(3)n=5首先m值为-2(输入的人数和初始密码不能为负数!)二、概要设计为实现上述程序功能,应利用单向循环链表存储结构模拟此过程。
1.单向循环链表的抽象数据类型定义为:ADT CircularList{数据对象:D={ai|ai∈LNode,i=1,2,…,n,n≥0}数据关系:R1={<ai-1,ai>|ai-1∈D,i=2,…,n}基本操作:Status ListDelete_L(LinkList &L,int I,ElemType &e)操作结果:在带头结点的单链表L中,删除第i个元素,并用e返回其值}2.本程序中包括的三个基本模块:1)主程序模块:Void main(){初始化;do{接受命令;处理命令;}while(“命令”=”退出”)}2)线性表模块:实现线性表的抽象数据结构3)元素结构单元模块:定义线性表中每个元素的结构三、详细设计1.结点类型typedef struct LNode{int data;//密码int i;//编号struct LNode *next;}LNode, *LinkList;2.用循环链表存储约瑟夫环,没有头结点,基本操作函数如下:int CreateList(LinkList &L,int a[],int n){//创建循环链表结构的约瑟夫环LinkList s,r;int i;r=L;for(i=1;i<=n;i++){s=(LinkList )malloc(sizeof(LNode));s->data=a[i];s->i=i;if(i==1){L=s;s->next=s;r=s;//尾指针指向当前元素}else{s->next=r->next;r->next=s;r=s;}}return 1;}int ListDelete_L(LNode *L){//删除表中一个结点if(L->next==L)//只剩一个结点{printf("%d\n",L->i);free(L);return 0;}LNode *p;p=L->next;//p指向要删除元素的下一个结点while(p->next!=L)p=p->next;LNode *q=L;//q指向需要被删除的元素结点int e=L->i;p->next=L->next;free(q);printf("%d ",e);return 1;}int FindNode(LinkList L,int x){//查找表中某个结点LinkList p=L;LinkList q;for(int i=1;i<x;i++)p=p->next;q=p->next;//下一次循环的起始位置x=p->data;if(ListDelete_L(p))FindNode(q,x);return p->i;}3.主函数:int main(){int n,m;LinkList L;printf("请输入人数和初始密码:");scanf("%d %d",&n,&m);if(n<0||m<0){printf("输入的人数和初始密码不能为负数!\n");return 0;}int a[20XXXX0];printf("请输入每个人的密码:");for(int i=1;i<=n;i++)scanf("%d",&a[i]);if(CreateList(L,a,n)){printf("\n");printf("正确的出列顺序为:");FindNode(L,m);printf("\n");}return 0;}4.函数的调用关系图反映了演示程序的层次结构:CreateList FindNodeListDelete_L四、调试分析1.刚开始时,忽略了题目要求的没有头结点这一项,没有把第一个结点单独拿出来建立,出现了逻辑上的错误。
数据结构实验第二章约瑟夫环
实验名称:约瑟夫环一.问题描述:设有编号为1,2,…,n的n(n>0)个人围成一个圈,每个人持有一个密码 m。
从第一个人开始报数,报到 m 时停止报数,报 m 的人出圈,再从他的下一个人起重新报数,报到 m 时停止报数,报 m 的出圈,……,如此下去,直到所有人全部出圈为止。
当任意给定n和m 后,设计算法求 n 个人出圈的次序。
二、数据结构设计由于约瑟夫环问题本身具有循环性质,故考虑采用循环链表的结构来存储信息。
为了统一对表中任意结点的操作,循环链表不带头结点。
其结点类型定义如下:typedef struct Node{int data;struct Node *next;}Node,*LinkList;三、算法设计(1)流程图定义L头指针,创建头结点创建循环链表求具体出圈顺序(2)详细说明:求出圈顺序://首先,定义L头指针,创建头结点LinkList L,p,q;i=1;L=(LinkList)malloc(sizeof(Node));L->data=i;p=L;//然后,创建循环链表for(i=2;i<=n;i++){ //n为总人数q=(LinkList)malloc(sizeof(Node));q->data=i;p->next=q;p=p->next;}p->next=L;p=L;//求具体出圈顺序while(1){i=1;while(i<m-1){ //m为密码p=p->next;i++;}if(p->next==p){ //判断是否到最后一个结点printf("\nthe last one is: %d\n",p->next->data);break;}else{++num;printf("\nthe %dth one is: %d",num,p->next->data);p->next=p->next->next;}p=p->next;}四、界面设计,此程序功能简单,无需复杂操作界面。
数据结构(五)-环形链表及约瑟夫问题
数据结构(五)-环形链表及约瑟夫问题⼀、单向环形链表的应⽤场景(约瑟夫问题)Josephu 问题为:设编号为1,2, ... n 的 n 个⼈坐成⼀圈,约定从编号为 k(n≥k≥1) 的⼈开始报数,数到 m 的那个⼈出列,她的下⼀位⼜从 1 开始报数,数到 m 的那个⼈⼜出列,以此类推,直到所有⼈出圈为⽌,因此形成⼀个出圈编号的序列⼆、单向链表的⽰意图三、创建环形链表图解创建环形链表代码实现// 创建单向环形链表class SingleCircularLinkedList{// 初始化⼀个头节点Girl first = null;// 添加数据到链表中public void add(int num) {// 校验参数if(num < 1) {System.out.println("您输⼊的⼩孩个数⼩于1,不能创建环形链表");}// 定义临时指针Girl curGirl = first;for(int i = 1; i <= num; i++) {Girl girl = new Girl(i);if(i == 1) { // 说明是第⼀个节点first = girl;first.setNext(first);curGirl = first;}else {curGirl.setNext(girl);curGirl = girl; // curGirl 后移curGirl.setNext(first); // 形成闭环}}}// 遍历链表public void list() {// 判断链表是否为空if(first == null) {System.out.println("当前链表为空");return;}// 定义临时指针Girl curGirl = first;while(true) {System.out.printf("⼩孩编号为 %d \n", curGirl.getNo());if(curGirl.getNext() == first) {break;}curGirl = curGirl.getNext();}}}// 创建节点类class Girl {private int no;private Girl next;public Girl(int no) {super();this.no = no;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public Girl getNext() {return next;}public void setNext(Girl next) {this.next = next;}}四、约瑟夫问题图解补充,设置 helper 节点的思路来源于单向链表删除节点时,指针始终指在当前节点的前⼀位,cur.next = cur.next.next代码实现// 约瑟夫问题public void joseph(int startNo, int countNum, int nums) {// 参数校验if(startNo < 1 || countNum > nums || nums < 1) {System.out.println("输⼊的参数有误");return;}// 定义临时指针Girl helper = first;// 让helper移动到first的上⼀个节点的位置,让first指针移动到startNo处(移动startNo - 1次) while(true) {if(helper.getNext() == first) {break;}helper = helper.getNext();}for(int i = 0; i < startNo - 1; i++) {first = first.getNext();helper = helper.getNext();}// 让first和helper同时移动countNum - 1次,⼩孩出圈while(true) {if(helper == first) { // 条件成⽴说明圈中只有⼀个⼩孩break;}for(int i = 0; i < countNum - 1; i++) {first = first.getNext();helper = helper.getNext();}// ⼩孩出圈操作System.out.printf("出圈的⼩孩为 %d 号\n", first.getNo());first = first.getNext();helper.setNext(first);}// 输出圈中留下的lucky girlSystem.out.printf("留在圈中的 lucky girl 为 %d 号\n", first.getNo());}。
数据结构约瑟夫环问题的课程设计
课程设计与内容要求约瑟夫环问题[问题描述]编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。
设计一个程序来求出出列顺序。
[基本要求]利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
此题所用的循环链表中不需要“头结点”,请注意空表和非空表的界限。
[测试数据]m的初值为20,n=7 ,7个人的密码依次为3,1,7,2,4,7,4,首先m=则正确的输出是什么?[要求]:输入数据:首先输入待处理人员数及他们的密码,然后输入m的初值,建立单循环链表。
输出形式:建立一个输出函数,将正确的出列序列输出。
一问题描述与分析约瑟夫问题编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。
设计一个程序来求出出列顺序。
分析利用单循环链表解决本问题,先创建一个有n个的单循环链表,依次录入密码。
然后从第一个结点出发,连续略过 m-1个结点,将第m个结点从链表中删除,并将第m个结点的密码作为新的么值,接着从下个结点开始,循环此过程,直至链表为空。
二数据结构描述利用不带头结点的单循环链表来作为约瑟夫环的存储结构三主要算法流程描述1主要流程图2具体程序段及其说明#include<stdio.h>#include<malloc.h>typedef struct node{int number;int key;struct node* next;}listnode, * circularlist;//定义了结点类型listnode和指针类型circularlistint main(){int amount,t,code,m,k;// amount表示总人数,code表示相应的学生密码circularlist w=(listnode*)malloc(sizeof(listnode));w->next=w;//循环链表仅一个元素时依然满足listnode *v;printf("请输入总人数:");scanf("%d",&amount);v=w;for(k=1;k<=amount;k++){printf("请输入第%d 学生的密码: ",k);scanf("%d",&code);w->key=code;w->number=k;if(k!=amount){w->next=(listnode*)malloc(sizeof(listnode));w=w->next;}w->next=v;}//循环结束后自动生成链表头printf(“约瑟夫环已建成,可以开始!\n”);printf("请输入初值: ");scanf("%d",&m);if(m<=0){printf("输入错误,请重新输入\n");return(1);}m=m-1;//使w提前停下printf("出列顺序是:");//用w为起始点do{t=0;//加入m减1后为零的情况while(t!=m){w=w->next;t++;}v=w->next;w->next=v->next;printf(" %d",v->number);m=v->key;m=m-1;free(v);//释放v的存储空间}while(w->next!=w);printf(" %d\n",w->number);free(w); //释放w的存储空间getchar();getchar();return(0);}四使用说明1进入C工作环境:如Turbo C2.0, Turbo C++ 3.0,Microsoft visual C++ 6.0(本次课程设计使用环境)2输入自己所编好的程序,通过键盘或软键盘。
数据结构经典题(一)Josephus(约瑟夫)问题
Josephus(约瑟夫)问题有n个人围成一个圈,从第1个人开始报数,数到第m个人,让他出局;然后从出局的下一个人重新开始报数,数到第m个人,再让他出局,……,如此反复直到剩下一个人,问此人编号为几?或:有n个人围成一个圈,从第k个人开始报数,数到第m个人,让他出局;然后从出局的下一个人重新开始报数,数到第m个人,再让他出局,……,如此反复直到所有人出列,由此产生一个出队编号的序列。
1、数组解法#include<iostream>#include<stdlib.h>using namespace std;const int n=11, m=3;int main(){int a[n],p=0;int i,k=0,number=0;for(i=0; i<n; i++) a[i]=i+1;while(number<n-1) //number表示出去的人数{ if(a[p]!=0) //p指向正要报数的人{ k++; //k为1,2,3...报数if(k==m) //报到m时,a[p]出去{ a[p]=0; k=0; number++; }}p=(p+1) % n; //下一个人}for(i=0; i<n; i++)if(a[i]!=0){ cout<<"最后一个获胜者的编号是:"<<i+1<<endl; break; }system("pause");}其中while循环也可改为:while(number<n-1) //number表示出去的人数{while(a[p]==0) p=(p+1) % n; //找到下一个报数的人k++; //k为1,2,3...报数if(k==m) //报到m时,a[p]出去{ a[p]=0; k=0; number++; }p=(p+1) % n;}2、链表解法#include<iostream>#include<stdlib.h>using namespace std;const int n=11, m=3;struct node{ int no;node *next;};int main(){int k=0;node *p,*q,*r;p=q=new node; //创建第一个节点p->no=1;for(int i=2; i<=n; i++) //建立链表{ r=new node;r->no=i;q->next=r;q=r;}q->next=p; //构成一个"环"q=p;while(q->next!=q){ k++; //k为1,2,3...报数if(k==m) //报到m时,删除q所指结点{ p->next=q->next;delete q;q=p->next;k=0;}else{ p=q; q=q->next; }}cout<<"最后一个获胜者的编号是:"<<q->no<<endl; system("pause");}其中while循环也可改为:while(q->next!=q){ for(int i=1; i<m; i++) //直接找到报m的人{ p=q; q=q->next; }p->next=q->next;delete q;q=p->next;}。
数据结构实验一约瑟夫(Joseph)问题
华北#########学院数据结构实验报告2011~2012学年第二学期级计算机专业班级:学号:姓名:实验一线性表及其应用一、实验题目:线性表及其应用——约瑟夫环二、实验内容:1.设带头结点的单链表ha和hb中结点数据域值按从小到大顺序排列,且各自链表内无重复的结点,要求:(1)建立两个按升序排列的单链表ha和hb。
(2)将单链表ha合并到单链表hb中,且归并后的hb链表内无重复的结点,结点值仍保持从小到大顺序排列。
(3)输出合并后单链表hb中每个结点的数据域值。
代码:实验结果:struct Node{ int data;Node* next; };typedef Node Slink;void create(Slink* h);void show(Slink* h);void merge(Slink* ha,Slink* hb);#include<iostream.h>void main(){cout<<"创建链表ha"<<endl;Slink ha; ha.next =NULL;create(&ha);cout<<"链表ha的节点排列"<<endl;show(&ha);cout<<endl;cout<<"创建链表hb"<<endl;Slink hb; hb.next =NULL;create(&hb);cout<<"链表hb的节点排列"<<endl;show(&hb);cout<<endl;cout<<"合并后链表hb的节点排列"<<endl;merge(&ha,&hb);show(&hb);}void create(Slink* h){if(!h) return;int n=0;//节点总数int j=0;//累计创建结点个数cout<<"请输入创建节点的个数"<<endl;cin>>n;Node* F=h;//F始终指向tou节点Node* pre=h;//pre始终指向要插入位置的前一个节点while(j<n){Node* p=new Node;cout<<"请输入节点的数据"<<endl;cin>>p->data;//链表为空时if(!F->next ){ F->next =p;p->next =NULL;j++;continue;}//链表不空时while(pre->next ){ if(p->data <pre->next ->data ){ p->next =pre->next ;pre->next =p;pre=h;j++;break;}else if (p->data ==pre->next ->data){ cout<<"该值已存在,请重新输入"<<endl;break;}pre=pre->next ;}if(!pre->next ){ pre->next =p;p->next =NULL;j++;}}}void merge(Slink* ha,Slink* hb){ //p遍历ha,q遍历hbNode * p=ha->next ;Node * q=hb->next ;//pw始终指向新生成链表的最后一个结点Node * pw=hb;while(p&&q){ if((p->data)<(q->data)){ pw->next=p;p=p->next;pw=pw->next;continue;}if((p->data)>(q->data)){ pw->next=q;q=q->next;pw=pw->next;continue;}if((p->data)==(q->data)){ pw->next=q;p=p->next;q=q->next;pw=pw->next;continue;}}while(p){ pw->next=p;p=p->next;pw=pw->next;}while(q){ pw->next=q;q=q->next;pw=pw->next;}pw->next=NULL;}void show(Slink* h){Node* p=h->next ;while(p ){ cout<<p->data <<" ";p=p->next ;}cout<<endl;}2.约瑟夫(Joseph)问题。
数据结构约瑟夫环问题
数据结构实验报告题目:约瑟夫环问题一.设计内容[问题描述]约瑟夫环问题的一种描述是:编号为1, 2, 3,…,n的n个人按顺时针方向围坐一圈,每人手持一个密码(正整数)。
一开始任选一个整数作为报数上限值,从第一人开始顺时针自 1 开始顺序报数,报到m 时停止报数。
报m 的人出列, 将它的密码作为新的m 值,从他在顺时针方向上的下一个人开始重新从 1 报数, 如此下去直到所有人全部出列为止。
试设计程序实现之。
[基本要求] 利用循环链表存储结构模拟此过程,按照出列的顺序打印各人的编号。
[ 实验提示] 程序运行后首先要求用户指定初始报数上限值。
然后读取各人的密码。
设n<=30 。
程序执行后,要求用户在计算机终端上显示“提示信息”后,用键盘输入“提示信息”中规定的命令,以“回车符”为结束标志。
相应的输入数据和运算结果显示在其后。
二、设计目的1. 达到熟练掌握C++ 语言的基本知识和技能;2. 能够利用所学的基本知识和技能,解决简单的面向对象程序设计问题。
3. 把课本上的知识应用到实际生活中,达到学以致用的目的。
三、系统分析与设计(确定程序功能模块)1、为实现上述程序的功能,应以有序链表表示集合。
基本操作:InitList(&L)操作结果:构造一个空的有序表L。
DestroyList(&L)初始条件:有序表L 已存在。
操作结果:销毁有序表L。
ListEmpty(L)初始条件:有序表L 已存在。
操作结果:若L为空表,则返回TRUE,否则返回FALSE。
ListLength(L)初始条件:有序表L 已存在。
操作结果:返回L 中数据元素个数。
GetElem(L,i)初始条件:有序表L已存在,并且K i< ListLength(L)。
操作结果:返回L 中第i 个数据元素。
LocatePos(L,e)初始条件:有序表L已存在,e和有序表中元素同类型的值。
操作结果:若L中存在和e相同的元素,则返回位置;否则返回0。
数据结构~约瑟夫问题
#include <stdio.h>#include <stdlib.h>struct JEnode{char name[10];long number;char sex[10];int age;char class_[10];char health[10];struct JEnode *next;};typedef struct JEnode student;student *creatJEnode(int n){student *head,*ps,*tail;int i;head=tail=NULL;for(i=0; i<n; i++){ps=(student*)malloc(sizeof(student));scanf("%s",ps->name);scanf("%ld",&ps->number);scanf("%s",ps->sex);scanf("%d",&ps->age);scanf("%s",ps->class_);scanf("%s",ps->health);ps->next=NULL;if(i==0)head=tail=ps;else{tail->next=ps;tail=ps;}}tail->next=head;return head;}void JEcancel(student *head,int m){student *p,*q;int j=1;p=head;q=NULL;while(p->next!=p){if(j==m-1){q=p->next;printf("%s ",q->name);printf("%ld ",q->number);printf("%s ",q->sex);printf("%d ",q->age);printf("%s ",q->class_);printf("%s",q->health);printf("\n");free(q);p->next=q->next;//让p指向q的下一个,重新开始计数*j=0;//这是删除是的状态,故j=0}p=p->next;//p指针不断的往后移动j++;}q=p->next;printf("%s ",q->name);printf("%ld ",q->number);printf("%s ",q->sex);printf("%d ",q->age);printf("%s ",q->class_);printf("%s",q->health);printf("\n");free(q);}int main(void){student *head;int total,mark;scanf("%d",&total);scanf("%d",&mark);head=creatJEnode(total);//printf("\n");JEcancel(head,mark);return 0;}。
数据结构课程设计报告(约瑟夫问题)
数据结构课程设计报告(约瑟夫问题)问题描述约瑟夫问题:编号为1-n的n个人围坐圆桌旁,从任一指定编号为k的人开始报数,报数为m的人离开圆桌,下一个人接着从n开始报数, 报数为m的人又离开圆桌,依此重复,直至所有人离开圆桌.编一程序,输出离开圆桌的人的编号序列.设计思想首先采单循环链表建立整个约瑟夫环,手动输入总人数(既链表的长度)、每个人的所持下一轮报数出对值和初始报数值。
node->num为人的编号,node->为此人所持的下一轮报数值。
建立单循环链表后,通过初始报数值找到出列的人,输出node->num的值,然后将该结点中的data值作为下一轮的报数值。
重复以上过程直至所有的人都出列,则程序结束。
主要算法do{k=1;while(k!=m)//当k=m时,结束第一轮报数{p1=p1->next;k++;}//报数中将指针指向下一位p2=p1->next;p1->next=p2->next;//把报数为m的人的结点从链表中删除printf("编号为%d的人出列,他的key%d作为新的m值/n",p2->num,p2->data);//m=p2->data;//报数为m的人的密码作为下一轮新的m值free(p2);//释放报m的人的结点}while(p1->next!=p1);//当p1->指向自己时,报数结束的值加一,当k=m时,此时p1指向人出列,p2指向该结点的上一结点,k为计数器,指针每移动一次,k让上一结点的next指向该结点的下一结点,然后删除该结点。
P1指向该结点下一结点,令k=1,再开始下一轮报数。
等到所有人出列后,循环结束。
for(i=1;i<=n;i++){printf("请输入%d号同学的key",i);scanf("%d",&j);//输入学生所带有的密码p1->next =(listnode*)malloc(sizeof(listnode));//建立一个空间p1=p1->next ;p1->data=j;p1->num=i;//对结点的num和data成员赋值p1->next=head->next; }定义指针p1,然后建立一个新结点并将p1->next指向他,再将地址赋给p1,最后将head->next赋给p1->next,构成了循环单链表,然后让所有人键入链表并给num和data成员赋值。
数据结构—约瑟夫环问题(循环单链表)
数据结构—约瑟夫环问题(循环单链表)n个数据元素构成⼀个环,从环中任意位置开始计数,计到m将该元素从表中取出,重复上述过程,直⾄表中只剩下⼀个元素。
解题思路:⽤⼀个⽆头结点的循环单链表来实现n个元素的存储。
循环单链表:尾指针指向头结点。
这样指针可以循环移动。
可以使⽤两个指针来操作,将指针q指向需要操作的结点上,指针p指向需要操作结点的前⼀个结点。
1 #include <stdio.h>2 #include <stdlib.h>3 #include <malloc.h>4 #include <math.h>5#define NULL 06 typedef struct LNode7 {8int num;///编号9struct LNode *next;10 } LNode, *Linklist;11 Linklist head,tail;12void Createlist(int n)///创建含有n个结点的单循环链表13 {14int i;15 Linklist p,q;16 head=(Linklist)malloc(sizeof(LNode));17 q=head;18 q->num=1;19for(i=2; i<=n; i++)20 {21 p=(Linklist)malloc(sizeof(LNode));22 p->num=i;23 q->next=p;24 q=p;25 }26 p->next=head;27 tail=p;///尾指针要指向头结点28 }29void Outlist(int k)30 {31int i;32 Linklist p,q;33 p = head;34for(i=1; i<k-1; i++)///循环k-2次35 {36 p = p->next;///指向需要操作元素的前⼀个指针37 }38 q = p->next;///指向需要操作元素的指针39while(q != p)40 {41 printf("%3d",q->num);42 p->next = q->next;///删除q所指向的元素43for(i=1; i<k; i++)///因为要经过已经删除的元素,所以需要多删除⼀次44 {45 p = p->next;46 }47 q = p->next;48 }49 printf("%3d\n",q->num);5051 }52int main()53 {54int k,n;55 printf("---------------约瑟夫环问题--------------\n");56 printf("\n请输⼊总⼈数和从第⼏个⼈开始报数n,k:\n");57 scanf("%d%d",&n,&k);58 Createlist(n);59 printf("\n出队的次序:\n");60 Outlist(k);61return0;62 }我看了⼀下我同学的做法,可以p直接使⽤尾指针,⽽q来⾃头指针,这样在遍历的时候,p指针⼀直会在q指针之前。
数据结构实验--约瑟夫环问题
线性表及其应用班级:软件101 姓名:xxx 学号:xxxxxxx 完成日期:2011-11-18 题目:编制一个求解约瑟夫环问题的程序一、需求分析//该题目的功能等需求、测试数据以及预期的输出结果等。
问题描述:编号为1,2,…,n的n个人按顺时针方向围坐一圈。
每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他顺时针方向的下一个人开始重新从1报数,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
(1):在本实验中,要求利用单向循环链表存储结构来完成,以便有效地掌握线性表相关知识及其应用。
(2):在程序运行后,首先指定一个初始报数的上限值m=20,然后输入各人的密码,假设n<=10;(3):编译执行后得到结果并进行检查核对。
(4):测试数据为:初始密码2,各成员密码分别为:2、7、1、8、、2、8、5 ;结束条件:输入0二、概要设计//数据结构的大概设计;程序模块的设计以及大概算法等。
为了实现上述程序功能,应以循环链表存储结构来表示;需要抽象数据类型有:(1):线性链表存储结构的定义struct JosephNode{int number;//编号int password;//密码struct JosephNode *next;};(2):数据结构类型的定义typedef struct JosephNode *JosephCircle;JosephCircle Init(void);JosephCircle CountOff(JosephCircle joseph , int& number , int& password); typedef struct JosephNode *PJoseph;三:详细设计//结构在程序设计语言中的表示;各函数的完整说明;所需函数的概要代码;函数调用关系等。
数据结构 约瑟夫环 课程设计
摘要:约瑟夫问题是由古罗马著名的史学家Josephus提出的问题演变而来,所以通常称为Josephus问题。
改进约瑟夫问题的描述是:编号为1,2,…,n的n 个人按顺时针方向围坐一圈,每人有一个密码Ki(整数),留作其出圈后应报到Ki后出圈。
报数方法采用顺时针报数和逆时针报数交替进行,初始密码可任意确定。
求最后剩下的人的编号。
这个就是约瑟夫环问题的实际场景,后来老师要求我们对要求中的每人所持有的密码以及第一次的报数上限值要用随机数产生。
因此约瑟夫环问题如果采用双向循环链表则能很好的解决。
循环链表的数据结构,就是将一个链表的尾元素指针指向队首元素。
p->link=head解决问题的核心步骤:先建立一个具有n个链结点,无头结点的循环链表,然后确定第一个报数人的位置,并不断地从链表中删除链结点,直到链表为空。
关键词:约瑟夫环;双向循环链表;数据结构;删除结点目录1需求分析 (3)1.1功能分析 (3)1.2设计平台 (3)2概要设计 (3)2.1类LinkList (3)2.2类Joseph (4)2.3类异常处理 (4)3详细设计和实现 (4)3.1创建结点Node (4)3.2创建双向循环链表 (5)3.3从链表中删除结点 (6)4调试与操作说明 (10)4.1调试情况 (10)4.2操作说明 (10)总结............................................ 错误!未定义书签。
致谢. (13)参考文献 (13)1需求分析1.1功能分析本次选做的课程设计是改进约瑟夫(Joseph)环问题。
我选择了和薛晶两个人来完成本次课程设计的作业。
约瑟夫环问题是一个古老的数学问题,本次课题要求用程序语言的方式解决数学问题。
此问题仅使用单循环链表就可以解决此问题。
而改进的约瑟夫问题通过运用双向循环链表,同样也能方便地解决。
在建立双向循环链表时,因为约瑟夫环的大小由输入决定。
约瑟夫环问题
1.约瑟夫环问题(实验类型:综合型)1)问题描述:有编号为1, 2…n 的 n 个人按顺时针方向围坐一圈,每人持有一个正整数密码。
开始给定一个正整数 m,从第一个人按顺时针方向自1开始报数,报到m者出列,不再参加报数,这时将出列者的密码作为m,从出列者顺时针方向的下一人开始重新自1开始报数。
如此下去,直到所有人都出列。
试设计算法,输出出列者的序列。
2)实验要求: 采用顺序和链式两种存储结构实现3) 实现提示:✧用顺序表来存储围座者的序号和密码(顺序存储结构).⏹用number 和code分别表示围座者的序号和密码.假设围座者人数为j,当前使用密码为m,开始报数者位置为s, 那么下一出列者位置为s=(s+m-1) mod j.⏹当我们要在线性表的顺序存储结构上的第i个位置上插入一个元素时,必须先将线性表的第i个元素之后的所有元素依次后移一个位置,以便腾空一个位置,再把新元素插入到该位置。
若要删除第i个元素时,也必须把第i个元素之后的所有元素前移一个位置。
✧用链式存储解决此问题时可以采用循环链表.4)注意问题:顺序存储和链式存储实现此算法时计算出列位置的不同方法,人员出列后所做操作的区别。
#include<stdio.h>#include<stdlib.h>typedef struct Node{int key;//密码int num;//编号struct Node *next;}Node,*Link;void InitList(Link &L){//创建空链表L=(Node*)malloc(sizeof(Node));if(!L)exit(1);L->key=0;L->next=L;}void Creatlinklist(int n,Link&L){//初始化链表Link p,q;q=L;for(int i=1;i<=n;i++){p=(Node*)malloc(sizeof(Node));if(!p)exit(1);scanf("%d",&p->key);p->num=i;L->next=p;L=p;}L->next=q->next;free(q);}Link Locate_m(Link &p,int m){//找到第m个Link q;for(int j=1;j<m;j++)p=p->next;q=p->next;m=q->key;return q;}void Delete_m(Link &L,Linkp,Link q){//删除第m个p->next=q->next;free(q);}int main(){Link L,p,q;int n,m;L=NULL;InitList(L);//构造一个只有头节点的空链表printf("输入初始密码:");scanf("%d",&m);//初始密码为m printf("输入总人数:");scanf("%d",&n);//总人数为nprintf("输入每个人手中的正整数密码:");Creatlinklist(n,L);//建立约瑟夫环p=L;printf("出列者顺序为:") ;for(int i=1;i<=n;i++){q=Locate_m(p,m);//找到第m个printf("%d ",q->num);Delete_m(L,p,q);//删除第m个}}5)实验心得:大部分的时间都用在了编程上,主要是因为C语言掌握的问题,C语言基础不好特别是对于C语言中链表的一些定义和基本操作不够熟练,导致在编程过程中还要不断的拿着c语言的教材查找,所以今后还要对C语言多练习,多动手,多思考。
约瑟夫环数据结构课程设计
约瑟夫环问题设计与实现摘要约瑟夫问题是由古罗马著名的史学家Josephus提出的问题演变而来,所以通常称为Josephus问题。
改进约瑟夫问题的描述是:编号为1,2,…,n的n 个人按顺时针方向围坐一圈, 每人有一个密码m(整数),留作其出圈后应报到m后出圈,依次类推,即可求出出列顺序。
因此约瑟夫环问题如果采用循环链表则能很好的解决。
循环链表的数据结构,就是将一个链表的最后一个节点指针指向第一个结点。
出列时,根据密码找到对应的人,打印其编号,将其密码赋值给m后,释放节点,形成新的约瑟夫环,直到所有人出列结束。
关键字:约瑟夫环;循环链表;出列顺序;释放节点;Design and Realization of the Joseph ringABSTRACTThe Joseph problem is the evolution proposed by ancient Rome famous historian Josephus and come, so often referred to as the Josephus problem. Improvement of Joseph problem description is: No. 1, 2,... N, n individuals according to a clockwise direction around a circle, each with a password of M (integer), keep the ring should be reported after the M ring, and so on, we can calculate the column order. So Joseph circle if using circular linked list can be very good solution. Circulation list data structure, is the last of a node is a pointer to a list of the points to the first node. Out, according to the code to find the corresponding person, print the number, the password is assigned to m, release the node, the formation of Joseph ring, until all the people out of the end.Keywords: Joseph ring; circular linked list; the column order release nodes;目录1需求分析 (1)1.1课题内容 (1)1.2要求 (1)2概要设计 (1)3详细设计 (2)3.1程序中的数据类型 (2)3.2函数运行过程详解 (3)4设计和调试分析 (6)4.1调试中遇到的问题 (6)4.2经验和体会 (7)5用户使用说明 (7)6测试数据和测试结果 (8)参考文献 (10)1 需求分析1.1课题内容:(1)本演示程序中,人数n应为任意的,首先应输入一个值赋给初始报数上限m,程序应能自动保存出列人的序号和将出列的人所持的密码赋给m,再次作为报数上限,如此循环,直至所有人都出列为止。
数据结构实验一约瑟夫问题
HUNAN UNIVERSITY课程实习报告题目:约瑟夫问题学生姓名刘海龙学生学号************专业班级软件1 3 0 1 指导老师李晓鸿完成日期 2 0 1 4 年11 月18 日一、需求分析1.输入的形式和输入值的范围本程序中,输入的人数n和报数值m均为整数,n、m均大于0,输入的形式为:n,m (n、m输入时用逗号隔开)2.程序功能提供用户从键盘输入约瑟夫环的关键数据,人数n和报数值m,并显示出列顺序。
3.输出的形式在DOS界面上输出这n个数的输出序列。
4.测试数据①输入(n,m均为正整数,且n>m)10,3输出3 6 9 2 7 1 8 5 10 4②输入(n,m均为正整数,且n<m)4,6输出2 1 4 3③输入(n,m均为正整数,且n=m)7,7输出7 1 3 6 2 4 5④输入 (n,m中有浮点数)8,5.56输出输入有误,请重新输入!⑤输入(n,m中有负数)-3,-8输出输入有误,请重新输入!⑥输入(n,m未按格式输入)aA2,3asf输出输入有误,请重新输入!二、概要设计抽象数据类型n(n为正整数)个人的编号为1~n,1相当于唯一的“第一元素”,n相当于唯一的“最后元素”,除最后元素n外,剩下的n-1个编号均有唯一的后继,除第一元素1外,剩下的n-1个编号均有唯一的前驱,符合线性结构,故应以线性表实现该结构。
ADT alist{数据对象:D={a i| a i∈int,i=1,2,…,n,n≥0}.数据关系:Rl={<a i-1,a i> | a i-1,a i∈D,i=2,…,n}基本操作:InitList(&L,size)//构造一个空线性表L。
Append(&L,e) //新元素e入表Remove(&L,i) //删除表中第i个元素,即将i之后的元素往前移一位。
DesList(&L)//销毁线性表,释放内存空间}无论选择哪种数据结构都应有一个结构初始化操作及相应的结构销毁操作,本程序的结构初始化操作为:InitList(&L,size),结构销毁操作为DesList(&L)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.2 程序代码
//建立循环链表函数
void initList(int n,LinkList &R)
{
R=(LinkList)malloc(sizeof(node));//创建一个带头结点的链表
cin>>R->data;
R->order=1;
R->next=R;
node *p,*q;
要求:(1)利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
(2)测试数据:m的初值为20,n=7,7个人的密码依次为3,1,7,2,4,7,4,首先m=6,则正确的输出是什么?
(3)输入数据:建立输入函数处理输入的数据,输入m的初值n,输入每个人的密码,建立单向循环链表。
(4)输出形式:建立一个输出函数,将正确的出列顺序输出。
for(int i=0;i<n;i++)
{
for(int j=0;j<k-1;j++)
p=p->next;
cout<<p->order<<" ";
k=p->data;
q=p;
p=p->next;
delet(q);
}
cout<<endl;
}
主函数
int main()
{
LinkList R;
int n,k;
q=R;
for(int i=1;i<n;i++)
{
p=(LinkList)malloc(sizeof(node));
int x;
cin>>x;//输入每个人所对应的密码
p->data=x;
p->order=i+1;
q->next=p;
q=p;
}
if(n>1)
p->next=R;
}
void delet(node *p)//删除结点的函数
1.2知识点
(1)掌握单向循环链表的建立。
(2)掌握单向循环链表的操作。
1.3输入输出分析
输入:对于约瑟夫环的输入采用的是单向循环链表,单向循环链表的结点包含两部分:一是数据域,它又包括对单向循环链表进行密码的输入和对密码对应的序列的输入;二是指针域。
输出:对于约瑟夫环的输出,需要输出结点数据域密码对应的序列,同时还要删除该结点,并释放该结点所对应的动态空间。
(1)图2 循环链表函数模块图
图2 循环链表函数模块图
(2)图3 输出函数模块图
图3 输出函数模块图
3 详细设计
3.1 数据类型实现
//构造结点结构体
typedef struct node
{
int data;//用来储存人的密码
int order;//用来储存人的序号
struct node *next;
3详细设计5
3.1数据类型实现5
3.2程序伪码5
4调试分析7
4.1问题分析与回顾7
4.2算法时空分析8
4.3算法改进8
4.4经验和体会8
5测试结果8
参考文献9
1 设计任务书
1.1 题目与要求
题目:编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。请设计一个程序求出出列顺序。
分析:指针代码的编写出现错误,使指针在一个节点删除后,不能够指向下一个结点。
解决:在输出函数中,使循环条件发生改变,使指针指向的数据直接为要输出的数据。
问题(2):在主函数中,使用do-while循环时,程序出现错误。
分析:while中的变量flag在循环体中被定义,造成系统识别不了该变量。
解决:将flag变量定义在循环体外。
4.2算法时空分析
循环链表函数的算法:由程序可知,在单循环链表函数中,用了一次for循环,其时间复杂度为O(n)。
删除结点函数的算法:在此函数中用了一次for循环,其时间复杂度为O(n)。
输出函数的算法:在此函数中用了两次for循环,其时间复杂度为O(n^2)。
输出函数 void putout(int n,int k,LinkList R)
结点删除函数 void delet(node *p)
2.2主程序流程图
(1)主程序调用模块图
图1 主程序调用模块图
2.3模块流程说明
主函数对各主要模块进行调用,各个主要模块又分别调用其他子模块。下面用简要流程图对各主要模块进行说明。
cout<<endl;
putout(n,k,R);
cout<<endl;
cout<<"还要继续吗,如果要,请输入1,否则输入其他数"<<endl;
cin>>flag;
}while(flag==1);
return 0;
}
4 调试分析
4.1 问题分析与回顾
问题(1):刚开始,在输入结点数据后,输出函数中序列输出的结果不正确。
1.4 测试数据分析
在程序运行结果出现的时候,对屏幕上出现的提示要按照其规则去完成,若是输入的不合法,则程序会结束。在提示是否要继续的时候:若是输入1,则继续;否则则停止。
2 概要设计
2.1 结构体类型及函数声明
(1)结构体
定义了一个有数据和指针的结构体node
(2)函数声明
循环n,LinkList &R)
int flag;
do
{
cout<<"总人数:";
cin>>n;
cout<<"报数上限值:";
cin>>k;
cout<<"请输入"<<n<<"个人的密码:"<<endl;
initList(n,R);
cout<<"密码的原序列号为:"<<endl;
for(int i=1;i<=n;i++)
cout<<i<<" ";
数 据 结 构 课 程 设 计
约瑟夫环
学 生 姓 名:张娟
学 号:131006432
指 导 教 师:刘双红
完 成 日 期:2014/6/7
1设计任务书2
1.1题目与要求2
1.2设计知识点2
1.3输入输出分析2
1.4测试数据分析3
2概要设计3
2.1结构体类型及函数声明3
2.2主程序流程3
2.3模块流程说明4
{
node *q;
q=p;
while(q->next!=p)
q=q->next;
q->next=q->next->next;//删除结点
free(p);//释放动态申请的结点空间
//输出函数
void putout(int n,int k,LinkList R)
{
node *p,*q;
p=R;
cout<<"正确的出列顺序为:"<<" ";