2009年02月24日星期二下午 05:03问题描述:约瑟夫环问题;有N个人围成一个环,从第一个人开始报数,报到M 的人退出环,并且由他的M值来代替原有的M值,要求输出离开环的顺序。
#include<iostream>#include<stdlib.h>using namespace std;//结点中数据域的类型定义typedef struct{int number;//标号int chipher;//手中的值}DataType;//带头结点的单循环链表typedef struct node{DataType data;struct node *next;}Scnode;//初始化void MyInit(Scnode **head)//指向指针的指针。
{if((*head=(Scnode *)malloc(sizeof(Scnode)))==NULL) exit(1);//动态分配 (*head)->next=*head;}//插入int MyInsert(Scnode *head,int i,DataType x){Scnode *p,*q;int j;p=head->next;j=1;while(p->next!=head&&j<i-1){p=p->next;j++;}if(j!=i-1&&i!=1){cout<<"erro!!!!!!!!!";return 0;}if((q=(Scnode *)malloc(sizeof(Scnode)))==NULL) exit(1); q->data=x;q->next=p->next;p->next=q;return 1;}//删除int MyDelete(Scnode *head,int i,DataType *x){Scnode *p,*q;int j;p=head;j=1;while(p->next!=head&&j<i-1){p=p->next;j++;}if(j!=i-1){cout<<"erro!!!!!!!!!";return 0;}q=p->next;*x=q->data;p->next=p->next->next;free(q);return 1;}//取数据元素int MyGet(Scnode *head,int i,DataType *x){Scnode *p;int j;p=head;j=0;while(p->next!=head&&j<i){p=p->next;j++;}if(j!=i){cout<<"erro!!!!!!!!!";return 0;}*x=p->data;return 1;}//判断是否为空int MyNotEmpty(Scnode *head){if(head->next==head) return 0;else return 1;}//删除P结点所指结点的下一个结点(也就是下面函数中的pre结点的下一个结点) void MyDelete(Scnode *p){Scnode *q=p->next;p->next=p->next->next;free(q);}//关键的函数void MyRing(Scnode *head,int m){Scnode *pre,*curr;int i;pre=head;curr=head->next;while(MyNotEmpty(head)==1)//这个喜欢是外层的把人循环完{for(int i=1;i<m;i++)//注意此处的循环是把当前m值下的人找出来。
{pre=curr;curr=curr->next;if(curr==head)//防止curr结点指向head,为什么呢,因为curr=curr-next移动过程中是要计数的{pre=curr;curr=curr->next;}}cout<<" "<<curr->data.number;m=curr->data.chipher;//这里重新赋值到新的密码m,注意此处的写法curr->data.chiphercurr=curr->next;//从下一个结点开始计数if(curr==head) curr=curr->next;//问题同上。
MyDelete(pre);//删除被指定到的结点}cout<<endl;}void main(){DataType test[7]={{1,3},{2,1},{3,7},{4,2},{5,4},{6,8},{7,4}};int n=7,m=20,i;Scnode *head;MyInit(&head);for(i=1;i<=n;i++)MyInsert(head,i,test[i-1]);MyRing(head,m);}数据结构:约瑟夫环问题的求解,链表数组,简单高效2008-03-25 14:59约瑟夫问题:12个人排成一圈,从1号报数,凡是数到5的人就走出队列(出局),然后继续报数,求最后一个出局的人。
编号为1,2,......,n的n个人按照顺时针方向围坐一圈。
从第一个人开始顺时针方向自1开始报数,报到m时停止报数。
报m 的人出列,从他在顺时针方向的下一个人开始重新报数,如此下去,直到所有人全部出列为止。
方法1:/*** 名称:** 描述:** Copyright: Copyright 2008* 创建日期 Mar 25, 2008* 作者 zhangtianshun* E-mail zhangts8888@* 版本 1.0*/public class JosephCircle {public JosephCircle() {// TODO Auto-generated constructor stub}public static int josephCircle(int totalNum, int perNum) { int count[] = new int[totalNum];for (int i = 0; i < count.length; i++) {count[i] = i + 1;}int flag = 0;int k = 0, n = 0;while (flag != 11) {for (k = 0; k < count.length; k++) {if (count[k] != 0) {n++;if (n % perNum == 0) {count[k] = 0;flag++;}}}}for (k = 0; k < count.length; k++) {if (count[k] != 0) {n = count[k];break;}}return n;}/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubint total = 12;int per = 5;JosephCircle joseph = new JosephCircle(); int last = -1;last = joseph.josephCircle(total, per);System.out.println("最后出列人的编号是: " + last); }}方法2:/*** 名称:** 描述:** Copyright: Copyright 2008* 创建日期 Mar 25, 2008* 作者 zhangtianshun* MSN zhangts8888@* E-mail zhangts8888@* 版本 1.0*/public class Josephus {/*** 约瑟夫环的求解思路:最简单的方法是用循环链表实现.* 现在用数组实现链表的效果.数组下标+1为数字编号,* 数组的值为下一个数组的地址.这样实现了链表的效果.* 当报数count=step-1时,删除下一个节点,节点值赋为-1. * 以此循环,直到数组元素都值为-1,最后删除的即为结果. */public Josephus() {super();}/*** 约瑟夫问题的求解* @param array 待处理的整形数组* @param size 待处理的数组长度* @param step 步长* @return Int 最后出列人的编号.*/public int joseph(int array[],final int size,final int step) { int flag = -1;//初始化数组链表,数组元素的值为下一个节点下标//即为: 1->2->3......(size-1)->0for(int i=0;i<size-1;i++)array[i] = i+1;array[size-1] = 0;/*** intRemain 当前剩下的有效节点* intDeleted 最好删除的一个节点的下班* intCurrent 当前数组元素的下标值* intCount 计数器*/int intRemain,intDeleted,intCurrent,intCount; intRemain = size;intDeleted = -1;intCurrent = 0;intCount = 0;do{//当前节点有效的标准是:不等于-1(flag)if(array[intCurrent] != flag){intCount++;//删除一个节点if(step - intCount == 1){//删除后一个节点,主要是将当前节点的向量指向下一个节点的下一个节点intDeleted = array[intCurrent];array[intCurrent] = array[intDeleted];array[intDeleted] = -1;intRemain--;intCount = 0;}}//当删除最好一个节点元素后,intCurrent的值变为-1.这之后数组就不能再被访问了. intCurrent = array[intCurrent];}while(intRemain !=0 );return intDeleted +1 ;}/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubchar num = '7';System.out.println((int)num);int array[] = new int[12];//人数int size = 12;//出局的倍数int step = 5;int last = -1;Josephus ysf = new Josephus();last = ysf.joseph(array, size, step);System.out.println("最后出列人的编号是: "+last);单循环链表解决约瑟夫环问题]约瑟夫问题的:编号为1,2,....,N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。