维基百科: 约瑟夫环问题
通过循环链表实现约瑟夫环
- 要求:1)要求设计一个程序模拟次过程,输入总的人数n,所报的出列的数字k,计数开始的位置p;
- 程序所能达到的功能:构造链表;输入数据;执行报数;储存出列人的序号,删除出列人的信息以及把指向出列人的指针移到出列人的下一个人,然后重新开始执行报数;直到最后一个人报数完毕,程序结束。
- 测试数据:n=9,9个人的序号分别为:1,2,3,4,5,6,7,8,9。然后p=1,从第一个开始报数。k=5,则确定输出的序列为:5,1,7,4,3,6,9,2,8。
例: 41个人从1开始报数,报到3的出列,则最后剩下的是31号
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
typedef struct Node
{
int num;
struct Node *next;
} LinkList;
LinkList *creat(int n)
{
LinkList *p, *q, *head;
int i = 1;
p = (LinkList *)malloc(sizeof(LinkList));
p->num = i;
head = p;
for (i = 2; i <= n; i++)
{
q = (LinkList *)malloc(sizeof(LinkList)); //Malloc()向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
q->num = i;
p->next = q;
p = q;
}
p->next = head; //使链表尾指向链表头 形成循环链表
return head;
}
void fun(LinkList *L, int pos, int cnt)
{
int i;
LinkList *p, *s, *q;
p = L;
printf("出列顺序为:");
while (p->next != p)
{
for (i = 1; i < cnt; i++) /*从1开始*/
{
q = p;
p = p->next;
}
printf("%5d", p->num);
s = p;
q->next = p->next;
p = p->next; //使p指向新的起点
free(s);//free()与malloc()函数配对使用,释放malloc函数申请的动态内存
}
printf("%5d\n", p->num);
}
int main()
{
LinkList *L;
int n;
cin>>n;
int pos;
cin>>pos;//从pos开始报数
int cnt;//报到cnt的出列
cin>>cnt;
L = creat(n);
fun(L, pos,cnt);
return 0;
}
更加简单点的写法:
#include<iostream>
#include<stdio.h>
using namespace std;
struct Node
{
int num;
Node *next;
};
Node *creat(int n)
{
Node *p, *q, *head;
int i =1;
p = new Node;
p->num = i;
head = p;
for(i = 2; i <= n; i++){
q = new Node;
q->num = i;
p->next = q;
p = q;
}
p->next = head;
return head;
}
void fun(Node *L, int pos, int cnt)
{
int i;
Node *p, *s, *q;
p = L;
cout<<"出列顺序为:";
while(p->next != p){
for(i = 1; i < cnt; i++){
q= p;
p = p->next;
}
printf("%5d",p->num);
s = p;
q->next = p->next;
s = p;
q->next = p->next;
p = p->next;
}
printf("%5d\n", p->num);
}
int main()
{
Node *L;
int n;
cin>>n;
int pos;
cin>>pos;
int cnt;
cin>>cnt;
L = creat(n);
fun(L, pos, cnt);
return 0;
}