用循环链表实现约瑟夫环

zhangchen2008_2008 2002-06-27 10:07:53
1 问题描述:编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)开始任选一个正整数作为报数值,自第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他持有的密码作为新的m值,从他的顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。编写完整的程序求出出列顺序。
2 具体要求:
(1)输入:从键盘输入人数n,n个人的密码,及初始m 值。输入应有提示,输入数据错误应当有出错提示,然后退出。当输入n值过大,而输入的n个整数不够时应有处理措施,将其补够n个整数。
(2)输出:输出最好是写到文件中,将原输入的值n,n个整数,初始m值均写入到文件中,出列顺序也写入到文件中,这样文档编制人员将其插入即可。
...全文
696 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
alonejilin 2002-08-12
  • 打赏
  • 举报
回复
我自己也写了一个:

下面是头文件:

"循环链表类定义.h"
#include<stdlib.h>
#include<iostream.h>

enum Boolean{False,True};
template <class Type> class CircList;
template <class Type> class CircListNode{
friend class CircList<Type>;
public:
CircListNode(Type d=0,CircListNode<Type>*next=NULL):data(d),link(next){}
private:

Type data;
CircListNode<Type> *link;



};
template <class Type> class CircList{
public:
CircList(Type value);
~CircList();
int Length()const;
Boolean IsEmpty();
Boolean Find(const Type&value);
Type GetData()const{if(current!=NULL)return current->data;}
void Firster(){current=first;}
Boolean First();
Boolean Next();
Boolean IsFirst();
Boolean Prior();
Boolean PriorIsFirst();
void Insert(const Type value);
void Remove();
void Josephus(int n,int m);

private:
CircListNode<Type> *first,*current,*last;
};
template <class Type>CircList<Type>::CircList(Type value)
{
last->link=first=last=new CircListNode<Type>(value);
current=NULL;
}
template <class Type>CircList<Type>::~CircList()
{
CircListNode<Type> *q;
while(first->link!=first){
q=first->link;
first->link=q->link;
delete q;
}
last=first;
delete first;
}
template <class Type>int CircList<Type>::Length()const{
CircListNode<Type>*p=first->link;
int count=0;
while(p!=first){p=p->link;count++;}
return count;
}
template <class Type>Boolean CircList<Type>::Find(const Type &value){
CircListNode<Type>*p=first->link;
while(p!=first&&p->data!=value)p=p->link;
if(p!=first){current=p;return True;}
return False;
}
template <class Type>Boolean CircList<Type>::IsEmpty()
{
if( first->link==first)return True;
else return False;
}

template <class Type>Boolean CircList<Type>::First()
{
current=first->link;
if(current==first){current=NULL;return False;}
return True;

}

template <class Type>Boolean CircList<Type>::Next()
{
if(IsEmpty()) return False;

current=current->link;
//if(current==first) current=current->link;
return True;


}
template <class Type>Boolean CircList<Type>::IsFirst()
{
if(current==first)return True;
return False;
}
template <class Type>Boolean CircList<Type>::PriorIsFirst()
{
if(first->link==current)return True;
return False;
}
template <class Type>Boolean CircList<Type>::Prior()
{
CircListNode<Type>*p=current;
if(IsEmpty())return False;
while(current->link!=p)current=current->link;
return True;

}
template <class Type>void CircList<Type>::Insert( const Type value)
{
last=current=last->link=new CircListNode<Type>(value,first);
}
template <class Type>void CircList<Type>::Remove()
{
if(current!=NULL&¤t!=first)
{
CircListNode<Type>* p=current;
Prior();
current->link=p->link;
if(p==last)last=current;
Next();//当前结点是删除结点的后继结点
delete p;
}

}
template <class Type>void CircList<Type>::Josephus(int n,int m)
{
First();
for(int i=0;i<n-1;i++){
for(int j=0;j<m-1;j++)
{

Next();
if(IsFirst())Next();
}
cout<<"出列者: "<<GetData()<<"\n";
Remove();
if(IsFirst())Next();
}
cout<<"获胜者:"<<GetData();
}

下面是执行文件:

#include"循环链表类定义.h"

void main()
{
CircList<int >clist(0);

int n,m;
cout<<"输入人数和报数:";
cin>>n>>m;
for(int i=1;i<=n;i++)
clist.Insert(i);

clist.Josephus(n,m);
}

希望对你有所帮助。
Micro_J 2002-07-18
  • 打赏
  • 举报
回复
约瑟夫环的标准算法是动态规划,而不是模拟!!!
alidiedie 2002-07-10
  • 打赏
  • 举报
回复
关注,学习,收藏.
xiaonian_3654 2002-07-05
  • 打赏
  • 举报
回复
为什么这么麻烦,大家可以用数组就可以实现,删除了哪个,将哪个标一下
再循环Just Do it!
南瓜皮 2002-06-28
  • 打赏
  • 举报
回复
更正:再写文档时,由于粗心,出队序列一处写错。正确如下(程序没有错误)
【测试数据:】
……正确的出队序列应为6,1,4,7,2,3,5)……
南瓜皮 2002-06-28
  • 打赏
  • 举报
回复
我提供一份比较完全的文档。由于不能粘贴图片,所以程序执行过程的窗口没有。该程序的执行环境为turbo c20
【概要设计:】
为实现以上功能,应以循环线性表表示该抽象模型。在此,我们用了动态线性存储结构——循环链表(该循环链表不含头节点)表示。
1. 本程序包含两个模块:
1) 建立循环链表模块:
struct node *CreatCycLkList()
该函数返回指向循环链表的第一个节点的指针.
2) 主程序模块:
void main(){
初始化;
调用建立循环链表模块;
while(链表中节点个数不为一个时){
查找下一个要出队列的结点;
输出该节点在原队列中的位置;
}
输出最后一个节点在原队列中的位置;
}
【详细设计:】
程序源码:
/*///////////// 预处理 //////////////*/
#define LEN sizeof(struct node)
#include "stdio.h"

/*///////////// 结点定义 /////////////*/
struct node{
int data;
int No;
struct node * next;
};

/*////////// 建立循环链表函数 /////////*/
struct node *CreatCycLkList()
{
struct node *head,*p1,*p2;
int n=0;

p1=p2=(struct node *)malloc(LEN);
printf("\ninput the %d pwd:",n+1);
scanf("%d",&p1->data);
p1->No=n+1;
head=NULL;

while(p1->data!=0){
n++;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct node *)malloc(LEN);
printf("input the %d pwd:",n+1);
scanf("%d",&p1->data);
p1->No=n+1;
}
p2->next=head;
return(head);
}

/*////////// 主函数 /////////*/
main()
{
int pwd;
struct node *head,*prior,*p,*s;

printf("please input the first password:");
scanf("%d",&pwd);
printf("\n");
head=CreatCycLkList();
p=head;

while(p!=p->next){
while(pwd!=1){
prior=p;
p=p->next;
pwd--;
} /*///// 内while语句为了查找下一个要出队列的结点; //////*/

printf("%d ",p->No);
pwd=p->data;
s=p; /*s是临时节点*/
prior->next=p->next; /*从表中删除刚出队列的节点*/
free(s);
p=prior->next;
}
printf("%d",p->No); /* 输出最后一节点的原位置编号*/
}
【调试过程:】
略.
【测试数据:】
m(即程序中的pwd)的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,正确的出队序列应为6,1,4,7,2,3,6)。执行如下图:(图中输了8个pwd值,其中最后一个为零,这是因为零是结束标志)


kbsoft 2002-06-27
  • 打赏
  • 举报
回复
typedef char datatype;
typedef struct node{
datatype info;
struct node * next;
}NODE;

void joseph(int n,int s,int m){
int i,j;
NODE *creatlinklist(int); /*建立链表*/
NODE *h,*p,*q,*r;
if(n<s) return;
h=creatlinklist(n);
q=h;
for(i=1;i<s;++i) q=q->next;
p=q->next;
for(i=1;i<n;i++)
{ for(j=1;j<m;++j)
if((p->next!=NULL)&&(q->next!=NULL))
{q=q->next;
p=p->next;}
else if(p->next==NULL)
{q=q->next;
p=h->next;}
else{
q=h->next;
p=p->next;}
printf("%c\n",p->info);
r=p;
if(p->next==NULL)
{p=h->next;
q->next=NULL;}
else {p=p->next;
if(q->next!=NULL) q->next=p;
else h->next=p}
free(r);
}
printf("%c\n",(h->next)->info);
}


NODE *creatlinklist(int n)
{ int i;
NODE *head,*p,*q;
if(n==0)return(NULL);
head=(NODE *)malloc(sizeof *head);
q=head;
for (i=1;i<=n;i++)
{p=(NODE *)malloc(sizeof *head);
printf("输入数据:\n");
p->info=getche();
printf("\n");
q->next=p;
q=p;}
p->next=NULL;
return(head);}
xrbeck 2002-06-27
  • 打赏
  • 举报
回复
easy 啊,单向循环链表OK。。
kbsoft 2002-06-27
  • 打赏
  • 举报
回复
是作业吧,呵呵

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧