using namespace std
struct person
{
unsigned int number
unsigned int key
person *next
}
//约瑟夫环类,此类包含多个person类,并控制输入输出.
class joseph_ring
{
private:
unsigned int n//用于存放人数
unsigned int m//用于存放初始密码
person *head//链表的头结点
public:
joseph_ring(){m=0n=0head=NULL}//构造函数,把成员变量赋初值
void create()//建立环的成员函数
void show()//运算并输出的成员函数
}
void joseph_ring::create()
{
cout<<"请输入人数:"
cin>>n
cout<<"请输入m的初值:"
cin>>m
//定义2个临时指针
person *p1,*p2
//for循环中用于初始化环
for(int i=1i<=ni++)
{
p1=new person//新实例化一个"人"的对象
p1->number=i//给这个"人"编个号
cout<<"请输入第 "<<i<<"个人对应密码:"
cin>>p1->key//给这个"人"一密码
//如果当前链表为空,头结点指向第一个"人"
if(i==1)
{
head=p1
p2=p1
}
//否则,p2永远指向尾结点,新建的结点都接到p2之后
else
{
p2->next=p1
p2=p1
}
}
p2->next=head//把链表连成一个循环链表(就是一个环)
}
void joseph_ring::show()
{
person *p1,*p2,*p
p1=head
//有n个人,所以执行n次循环
for(int i=1i<=ni++)
{
int count=1
//用count定位到第m个出圈人,循环后,p1指向这个出圈人,p2指向这个出圈人的上一个人
while(count++<m)
{
p2=p1
p1=p1->next
}
cout<<p1->number<<"\t"//输入当前出圈人的编号
m=p1->key//把当前出圈人的密码作为指向下一个出圈人所要经过的人数
p=p1//p指向当前这个出圈人
p2->next=p1->next//把出圈人前的人和出圈人后的人连上.
p1=p1->next//下次从当前出圈人的下一个人开始数
delete p//把出圈人毙掉(就是释放这块内存)
}
cout<<endl
cin>>m
}
int main()
{
joseph_ring j
j.create()
j.show()
return 0
}
这没啥高手的,人称入门题目,也就是说,会做这个基本就可以用C做一些东西了。这是我以前写的,从博客上面搞下来的,你试试看能不能运行,我当时似乎是运行过了的。不过这个不是用链表做的,用数组做的,你结合链表的语法把他改一下就行了,很简单的,就一个结构体而已么,反正基本思路这样就对了。另外对了,当时水平有限还不懂动态分配内存,你去查一下malloc函数的用法,觉得合适可以加进去,你用new命令也可以动态分配内存,具体的可以去看看MSDN,MSDN好东西啊。#include<stdio.h>
#include<stdlib.h>
void main()
{
int a[100]/*用来放环里的每个人的,人口上限(好像在打魔兽争霸)100,当然可以再改大*/
int n,r,ctor,u/*n是用来循环赋值的,给r个人循环赋1~u,一共r个人,ctor计数器,到了u再重新归1*/
int call(int a[],int real,int u)/*报数函数*/
for(n=0n<=99n++)a[n]=0/*给所有元素赋值为0,这样以后没赋值1~u的就都为0,可以当作不存在*/
printf("/约瑟夫环 JOSEPHUS/\n\n")
printf("输入参与报数的人数\n")
scanf("%d",&r)
printf("输入报数上限\n")
scanf("%d",&u)
ctor=1
for(n=0n<rn++) /*这个循环里给输入的人数都赋值,从1到u,相当于报的数*/
{
*(a+n)=ctor
ctor++
if(ctor>u)ctor=1
}
call(a,r,u)system("pause")/*调用点名函数*/
}
int call(int a[],int real,int u)
{
int n1,i
int *p
p=(a+u-1)
n1=0i=u
for(n1<real-1p++)
{
if(p>(a+real-1))p=a/*如果点名点过了,就接着队伍没有出列的第一个人继续*/
if(*(p)!=0) /*如果扫描的数字不为零,说明这个人还在队列中,那么看下面*/
{
if(i>u)i=1/*由于是剩下的人继续报数,所以当报到u这个上限时,还是要从新归1*/
if(i==u) /*当到达上限,说明这个人该出列啦,它的位置就填充为0*/
{
*(p)=0n1++/*n1计算着一共多少人出列,通过n1<real-1,可以留下最后一个人,这是最终目的*/
}
i++
}
}
for(i=0i<reali++) /*从新扫描数组,发现不是0的就输出,到这时候肯定只剩一个数不是0了*/
if(*(a+i)!=0)printf("所剩最后一位原来的呼号是%d\n\n",i+1)
}
写完了
正好之前写过基础的约瑟夫环,稍作修改就可以满足你的题目
#include <stdio.h>#include <stdlib.h>
typedef struct _node {
int id
int key
struct _node *next
} Linklist
int main() {
int n, m
scanf("%d %d", &n, &m)
int i, count = 0
Linklist *head = (Linklist*)malloc(sizeof(Linklist)), *tail = head
head->id = 1
scanf("%d", &head->key)
head->next = head
for(i = 2 i <= n i++) {
Linklist *p = (Linklist*)malloc(sizeof(Linklist))
p->id = i
scanf("%d", &p->key)
p->next = head
tail->next = p
tail = p
}
while(head != tail) {
if(++count % m) {
tail = head
} else {
m = head->key
count = 0
printf("%d ", head->id)
tail->next = head->next
free(head)
}
head = tail->next
}
printf("%d\n", head->id)
free(head)
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)