C语言约瑟夫环链表

#include <stdio.h>
#include <windows.h>
#include <string.h>
struct link * creat1(int n);
void out(struct link * head);
void free_(struct link * head);
struct link * jsf(struct link * head,int m);


struct link
{
int data;
struct link * next;
};


void main()
{
    struct link * head;
struct link * p;
int n,m;
printf("input n , m:");  //读入个数与约定删除数
scanf("%d %d",&n,&m);
head = creat1(n);
out(head);
p = jsf(head,m);
printf("\nlast: %d \n",p->data);
free(p);


}


struct link * jsf(struct link * head,int m)
{
    int i;
struct link * p = malloc(sizeof(struct link ));    //给无头结点链表添加辅助头结点,但循环链表的尾巴仍指向第一个元素点,而不是头结点
    struct link * q;
p->next = head;
head = p;
while(p->next != p) //只剩下一个节点时,即为结果
{
for(i = 0; i < m; i++)  //数到M删除一次
{
q = p;
p = p->next;
}
q->next = p->next;
free(p);
p = q;
}
free(head);//删除头结点
    return p;
}


struct link * creat1(int n)    //创建循环链表
{
    struct link * head;
    struct link * p;
struct link * q;
    int i = 1;
head = (struct link *)malloc(sizeof(struct link));
p = q = (struct link *)malloc(sizeof(struct link));
    p->data = i;
head->next=p;
while (i < n)
{
i++;
p = (struct link *)malloc(sizeof(struct link));
p->data = i;
q->next = p;
q = p;
}
p = head->next;   //删除头结点。使之为无头结点链表,多此一举,懒得改
    q->next = p;
free(head);
return p;
}


void out(struct link * head)  //输出无头结点链表
{
    struct link * p = head->next;
    printf("%d ",head->data);
while(p != head)
{
printf("%d ",p->data);
p = p->next;
}
putchar(10);
}


void free_(struct link * head)   //删除无头结点链表,未使用
{
    struct link * p = head->next;
struct link * q = head;
while(head != p)
{
q = p->next;
        free(p);
p = q;
}
    free(head);
}
好的,我很乐意为您介绍如何使用C语言中的链表来实现约瑟夫环问题。 约瑟夫环问题是一个经典的数学和计算机科学问题。问题描述如下:有n个人(编号1,2,...,n)围成一圈,从第一个人开始报数,报到m的人出列,然后从下一个人重新开始报数,报到m的人再出列,依此类推,直到所有人都出列。求最后出列的人的编号。 下面是一个使用C语言链表实现约瑟夫环的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构 typedef struct Node { int data; struct Node* next; } Node; // 创建循环链表 Node* createCircularList(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; } prev = newNode; } prev->next = head; // 形成循环 return head; } // 模拟约瑟夫环过程 int josephus(int n, int m) { Node* head = createCircularList(n); Node* prev = head; // 找到最后一个节点 while (prev->next != head) { prev = prev->next; } while (head->next != head) { // 移动到要删除的节点的前一个节点 for (int i = 1; i < m; i++) { prev = head; head = head->next; } // 删除节点 printf("出列的人:%d\n", head->data); prev->next = head->next; free(head); head = prev->next; } int lastPerson = head->data; free(head); return lastPerson; } int main() { int n, m; printf("请输入总人数n:"); scanf("%d", &n); printf("请输入报数m:"); scanf("%d", &m); int last = josephus(n, m); printf("最后剩下的人是:%d\n", last); return 0; } ``` 这段代码的主要步骤如下: 1. 定义一个链表节点结构 `Node`。 2. 创建一个包含 `n` 个节点的循环链表,每个节点代表一个人。 3. 实现 `josephus` 函数来模拟约瑟夫环过程: - 使用两个指针 `head` 和 `prev` 来跟踪当前节点和前一个节点。 - 在每一步中,移动 `m-1` 次,然后删除当前节点。 - 重复这个过程直到只剩一个节点。 4. 在 `main` 函数中,读取输入并调用 `josephus` 函数。 这个实现的时间复杂度是 O(nm),空间复杂度是 O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值