循环链表实现约瑟夫环(C语言)

约瑟夫环问题,是一个经典的循环链表题。
约瑟夫环问题描述:已知 n 个人(分别用编号 1,2,3,…,n 表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 开始,还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,直到圆桌上剩余一个人。输出的最后一个人即为圆桌剩余的一人。

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
	int data;
	struct LNode *next;
}CLinkList;
CLinkList *creat(int n){
	CLinkList *head,*node,*end;
	int i=0;
	head=(CLinkList*)malloc(sizeof(CLinkList));
	head->data=1;
	end=head;
	for(i=2;i<=n;i++){
		node=(CLinkList*)malloc(sizeof(CLinkList));
		node->data=i;
		end->next=node;
		node->next=NULL;
		end=end->next;
	} 
	end->next=head;
	return head;
}
void findAndKillK(CLinkList * head, int k, int m) {
    CLinkList * p = NULL;
    CLinkList * tail = head;
    //找到链表第一个结点的上一个结点,为删除操作做准备
    //while (tail->next != head) {
        tail = head->next;
   // }
    p = head;
    //找到编号为k的人
    while (p->data != k) {
        tail = p;
        p = p->next;
    }
    //从编号为k的人开始,只有符合p->next==p时,说明链表中除了p结点,所有编号都出列了,
    while (p->next != p) {
        int i = 0;
        //找到从p报数1开始,报m的人,并且还要知道数m-1de人的位置tail,方便做删除操作。
        for (i = 1; i < m; i++) {
            tail = p;
            p = p->next;
        }
        tail->next = p->next;//从链表上将p结点摘下来
        printf("出列人的编号为:%d\n", p->data);
        free(p);
        p = tail->next;//继续使用p指针指向出列编号的下一个编号,游戏继续
    }
    printf("出列人的编号为:%d\n", p->data);
    free(p);
}
int main() {
    int n = 0, k = 0, m = 0;
    CLinkList * head = NULL;
    printf("输入圆桌上的人数:");
    scanf("%d", &n);
    head = creat(n);
    printf("从第几个人开始报数(k>1且k<%d):", n);
    scanf("%d", &k);
    printf("数到几的人出列:");
    scanf("%d", &m);
    findAndKillK(head, k, m);
    return 0;
}

输出结果

输入圆桌上的人数:5
从第几个人开始报数(k>1且k<5)1
数到几的人出列:2
出列人的编号为:2
出列人的编号为:4
出列人的编号为:1
出列人的编号为:5
出列人的编号为:3

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用循环链表实现约瑟夫环C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义循环链表节点结构体 typedef struct Node { int data; struct Node* next; } Node; // 创建循环链表 Node* createCircularLinkedList(int n) { Node* head = NULL; Node* prev = NULL; for (int i = 1; i <= n; i++) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = i; if (head == NULL) { head = newNode; } else { prev->next = newNode; } newNode->next = head; prev = newNode; } return head; } // 删除指定位置的节点 Node* deleteNode(Node* head, int position) { if (head == NULL) { return NULL; } Node* current = head; Node* prev = NULL; // 找到要删除的节点 for (int i = 1; i < position; i++) { prev = current; current = current->next; } // 删除节点 if (prev == NULL) { prev = current; while (prev->next != head) { prev = prev->next; } prev->next = current->next; head = current->next; } else { prev->next = current->next; } free(current); return head; } // 约瑟夫环算法 void josephusCircle(int n, int m) { Node* head = createCircularLinkedList(n); Node* current = head; printf("假设第一次从编号为1的人开始数,数到%d的那个人出环\n", m); for (int i = 1; i <= n; i++) { // 找到要出环的节点 for (int j = 1; j < m; j++) { current = current->next; } // 输出出环的节点 printf("第%d次出环的元素是%d\n", i, current->data); // 删除出环的节点 head = deleteNode(head, current->data); current = current->next; } } int main() { int n = 5; // 假设5个人围坐一圈 int m = 2; // 数到2的那个人出环 josephusCircle(n, m); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值