(最下边有完整代码,中间部分仅提供思路,有残缺)
问题如图描述,这里主要用循环链表的方法实现,关于约瑟夫环的具体描述可以参考一下百度百科
ok,废话少说开始上代码讲解
首先是定义单链表节点(这点就不细说了)
#define _CRT_SECURE_WARINGS1
#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
int data;
struct Node* next;
}Node;
然后设置一个约瑟夫环的函数:
void ysflb(int n, int k){}
其中n为环内元素个数,k为出局数,比如n=10,k=3就是相当于有10个人,喊到3的人出去
很明显我们需要设置一个循环链表,n等于几就要设置几个节点
我们先设置一个头节点
head = (Node*)malloc(sizeof(Node));
head->data = 0;
head->next = NULL;
当然我们的头节点是不能动的,还要设置一个p指针便于扫描,并令p=head
Node*p=NULL;
p=head;
有了头节点我们就可以接着添加我们需要的节点,形成一个链表,这里用尾插法来进行插入
for (int i = 1; i < n; i++) //for循环
{
r = (Node*)malloc(sizeof(Node)); //创建一个新的节点
r->data = i; //将当前i的值赋给新节点r的data域
r->next = NULL; //因为用的尾插法所以将新节点的next指向NULL
p->next = r; //p最开始是在头指针,将p节点与r相连接
p = r; //p向前移一位
}
head->data = n; //for循环创建n-1个节点,将n值赋给头节点,使其不为空
p->next = head; //将最后一个r节点与头节点相连形成循环链表
p = head->next; //p指针重新回到头节点位置
链表创建完成就可以进行报数操作了
记得在报数前验证一下链表是否为空,避免交的时候报错
while (p->next != p) //判断是否为空链表
{
for (int i = 1; i < k; i++) {
r = p;
p = p->next;//此时轮到p出局
}
printf("%d ", p->data); //输出该p值
r->next = p->next; //删除p
p = p->next ; //p指针指向下一个
}
printf("%d", p->data);//输出剩余值
}
函数部分到这里就结束了,下面是主函数执行部分
int main() {
int n, k;
scanf("%d%d", &n, &k);
ysflb(n, k);
}
完整代码如下
#define _CRT_SECURE_WARINGS1
#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
int data;
struct Node* next;
}Node;
void ysflb(int n, int k) {
Node* head = NULL, * p = NULL, * r = NULL;
head = (Node*)malloc(sizeof(Node));
head->data = 0;
head->next = NULL;
p = head;
for (int i = 1; i < n; i++) {
r = (Node*)malloc(sizeof(Node));
r->data = i;
r->next = NULL;
p->next = r;
p = r;
}
head->data = n;
p->next = head;
p = head->next;
while (p->next != p)
{
for (int i = 1; i < k; i++) {
r = p;
p = p->next;//此时轮到p出局
}
printf("%d ", p->data);
r->next = p->next;//删除p
p = p->next;//
}
printf("%d", p->data);
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
ysflb(n, k);
}
运行结果如下