当前位置:文档之家› 猴子选大王循环链表实现

猴子选大王循环链表实现

C++n只猴子围成一圈,顺时针方向从1到n编号。

之后从1号开始没顺时针方向让猴子从1,2,...,m依次报数,凡是报到m的猴子,就让其出圈,取消候选资格。

然后不停地按顺时针方向逐一让报到m者出圈,是的剩下的一个就是猴王。

#include <iostream>using namespace std;struct monkey //结构声明{int num; //整型数,用于记录猴子号monkey *next; //monkey结构指针};monkey *head,*tail; //monkey结构指针,全局变量void creat(int nn) //被调用函数{ //函数体开始int i; //整型变量i,用于计数monkey *p,*q; //声明monkey结构指针p,qp=new monkey; //为p分配内存空间p->num=1; //初始化p结点num域为1p->next=NULL; //初始化p结点next域为空head=p; //链表头指针head赋值为pq=p; //q赋值为pfor(i=2;i<=nn;i=i+1) //利用循环结构构造链表{p=new monkey; //为p配内存空间p->num=i; //初始化p结点num域为i,表示猴子号q->next=p; //将p点加到链表尾部q=p; //让指向链表尾部结点p->next=NULL; //链表尾部指向空}tail=q; //链表尾tail->next=head; //链表尾部指向链表头,形成循环链表}//被调用函数select,mm表示结点删除间隔void select(int mm){ //函数体开始int x=0; //声明整型值x,并初始化为0monkey *p,*q; //声明指针变量p,qq=tail; //q赋值给tail,指向循环链表尾部do //直到型循环,用于循环删除指定间隔的结点{p=q->next; //p赋值给相邻的下一个结点x=x+1; //x加1if(x%mm==0) //x是否整除mm{cout<<"被删除的猴子号为"<<p->num<<"号\n";q->next=p->next; //删除此结点delete p; //释放空间p=NULL;}elseq=p; //q指向相邻的下一个结点p}while(q!=q->next); //剩余结点数不为1,则继续循环head=q; //head指向结点q,q为链表中剩余的一个结点} //函数体结束int main() //函数体开始{int n,m; //声明整型变量n,mhead=NULL; //初始化head为空cout<<"请输入猴子的个数\n"; //提示信息cin>>n; //输入待插入结点的数据cout<<"请输入间隔\n"; //提示信息cin>>m; //输入间隔creat(n); //调用函数creat建立循环链表select(m); //调用函数select,找出剩下的猴子cout<<"猴王是"<<head->num<<"号\n"; //输出猴王delete head; //删除循环中最后一个结点return 0;} //函数体结束c//实现目标:分别列出出列的猴子,然后得出最后的大王,(我认为没必要猴子数m要大于n!..所以没有这方面的提示~~)//问题分析:通过对“猴子选大王”问题的分析,由于本题目的数据元素的个数不可预知,所以使用链表。

链表是动态的,可以在需要的时候增长和减少其长度,而数组是在编译时分派内存的,事业其大小是不可改变的,而且会出现内存浪费的情况。

我认为单循环链表能较好,在建立循环链表时,因为链表的大小由输入决定,因此与匹配的结点数也是变化的,所以要进行动态内存分配。

//测试用例:m=10;n=4,最后求出成为猴王的猴子号:结果:大王是5号:(太搞笑了,大家都用这个用例,第五号可真幸运!~)//不健全的地方:1.没有对输入为字母,非正数(例如0)进行出错判断,结果大王会是第一号猴子。

(我觉得也可以不改啊~~没有“正常的”猴子,下一个真正的猴子当然是大王)2.如果正数但是非整数,输出为……(我没试过=——=!)//猴子选大王源代码:#include"stdio.h"//用双引比尖括号好的原因是可以在本环境外部查找这个头文件滴..#include"stdlib.h"typedef struct Node{int data;struct Node *next;}Node,*LinkList;void CreatLinkList(LinkList *L,int m)// 创建循环链表 m为猴子总数{Node *p, *q;int i; (*L) = (LinkList)malloc(sizeof(Node));if ((*L) == NULL)//这里是什么意思?{printf("Memory allocation failed,goodbye~~");exit(1);}p = (*L);p->data = 1;//为什么错误数据会返回“第一号猴子”的值?是这里初始化的么?(如果是可以换成0的说~)for (i = 2; i <= m; i++){q = (LinkList)malloc(sizeof(Node));if (q == NULL){printf("Mmory allocation failed,goodbye~~");exit(1);}q->data = i;p->next = q;p = q;}p->next =(*L);}void King(LinkList *L, int n, int m){Node *p, *q;int k;int j = 1; p = (*L);for (; m > 1; m--){k = 1;while (k != n){p = p->next;k++;}printf("第%d个出队列的是%d号猴子,\n", j++, p->data);p->data = p->next->data;q = p->next;p->next = p->next->next;free(q);}printf("最终结果:大王是第%d号猴子。

\n",p->data);}int main(void){int m, n;LinkList L; printf("请输入猴子总数m,和数到那个猴子出队n,(逗号隔开):");scanf("%d%d",&m,&n);//在这后面加判断、提示部分。

for循环判断.. CreatLinkList(&L, m);King(&L, n, m);sistem("pause");return 0;}题目描述:n 只猴子要选大王,选举方法如下:所有猴子按 1,2 ……… n 编号并按照顺序围成一圈,从第 k 个猴子起,由1开始报数,报到m 时,该猴子就跳出圈外,下一只猴子再次由1开始报数,如此循环,直到圈内剩下一只猴子时,这只猴子就是大王。

输入数据:猴子总数n ,起始报数的猴子编号k ,出局数字m 输出数据:猴子的出队序列和猴子大王的编号代码修改了一天才完成,第一次是用多个函数写的,但是发觉C 语言没有引用参数这个特性,使得形参指针不能被直接修改,必须靠返回值来修改才行,这样太麻烦了...于是第二次写的时候就没有使用函数,直接在main()里完成了循环链表的操作,感觉应该没什么问题,哪位大牛看出问题跟我说下,thx...1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /*约瑟夫问题(猴子选大王)循环链表C 语言实现Slyar 2009.3.31*/#include <stdio.h>#include <stdlib.h>/* 定义链表节点类型 */typedef struct node{int data ;struct node *next ;}linklist ;int main ()19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 {int i , n , k , m , total ; linklist *head , *p , *s , *q ; /* 读入问题条件 */ printf ("请输入猴子的个数:"); scanf ("%d", &n ); printf ("请输入要从第几个猴子开始报数:"); scanf ("%d", &k ); printf ("请输入出局数字:"); scanf ("%d", &m ); /* 创建循环链表,头节点也存信息 */ head = (linklist *) malloc (sizeof (linklist )); p = head ;p ->data = 1;p ->next = p ;/* 初始化循环链表 */ for (i = 2; i <= n ; i ++) {s = (linklist *) malloc (sizeof (linklist )); s ->data = i ;s ->next = p ->next ; p ->next = s ; p = p ->next ; }/* 找到第 k 个节点 */ p = head ;for (i = 1; i < k ; i ++) {p = p ->next ; }/* 保存节点总数 */ total = n ;printf ("\n 出局序列为:"); q = head ;/* 只剩一个节点时停止循环 */ while (total != 1) {/* 报数过程,p 指向要删除的节点 */ for (i = 1; i < m ; i ++) {p = p ->next ; }/* 打印要删除的节点序号 */ printf ("[%d] ", p ->data );63646566676869707172737475767778798081828384/* q 指向p 节点的前驱*/while(q->next != p){q = q->next;}/* 删除p 节点*/q->next = p->next;/* 保存被删除节点指针*/s = p;/* p 指向被删除节点的后继*/p = p->next;/* 释放被删除的节点*/free(s);/* 节点个数减一*/total--;}/* 打印最后剩下的节点序号*/printf("\n\n猴子大王为第[%d] 号\n\n", p->data); free(p);//system("pause");return0;}实验二#include<iostream.h>#include<conio.h>#include<stdlib.h>#define OK 1#define ERROR 0#define OVERFLOW 0typedef int Status;typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;void CreatList_L(LinkList &L,int n){L=(LinkList)malloc(sizeof(LNode));L->next=NULL;int i; LinkList q,p;q=L;for(i=n;i>0;--i){p=(LinkList)malloc(sizeof(LNode));cin>>p->data;q->next=p;p->next=NULL;q=p;}}//尾插法void output(LinkList &L){ LinkList p;p=L->next;while(p){cout<<p->data;p=p->next;}}//输出函数Status ListInsert_L(LinkList &L,int i,int e){ LinkList p,s;int j;p=L;j=0;while(p&&j<i-1){p=p->next;++j;}if(!p||j>i-1)return ERROR;s=(LinkList)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return OK;}void main(){LinkList L;CreatList_L(L,4);output(L);ListInsert_L(L,2,5);output(L);}void CreatList_L(LinkList &L,int n){L=(LinkList)malloc(sizeof(LNode));L->next=NULL;int i; LinkList p;for(i=n;i>0;--i){p=(LinkList)malloc(sizeof(LNode));cin>>p->data;p->next=L->next;L->next=p;}}//头插法。

相关主题