约瑟夫环C语言链表实现

        约瑟夫环:设编号分别为1、2、3....、n的n个人围坐一圈,提前约定编号为k(1≤k≤n)的人从1开始计数,数到m的那个人淘汰出局,他的下一个人又从1开始计数,数到m的人再淘汰出局,依次类推,直到最后只剩一个人,他将获得胜利。
设n=8,k=3,m=4时,如下图

 则淘汰序列为:6、2、7、4、3、5、1、8
最终存活者编号为8


算法思路:用头插法构建一张单向循环链表,结点内保存的数据即为编号。首先找到第k个结点,然后开始从1计数,计到m时删除该结点;然后从被删除结点的下一结点起又从1计数,直到最终只剩一个结点时循环结束,输出最终存活者编号。

以下为源代码,另外包含单向循环链表的一些基本操作和链表合并等

/*===============================================
*   文件名称:list.h
*   创 建 者:xm     
*   创建日期:2022年07月29日
*   描    述:
================================================*/
#ifndef _LIST_
#define _LIST_
#include <stdio.h>
#include <stdlib.h>

typedef int data_t;
typedef struct linklist
{
    data_t data;//数据域
    struct linklist *next;//指针域
}LinkList;

//创建头节点
LinkList *Creat_Linklist();
//判空
int Linklist_Is_Empty(LinkList *h_node);
//求表长
int Linklist_length(LinkList *h_node);
//从表头插入数据
void Linklist_Insert_head(LinkList *h_node,data_t data);
//打印
void Linklist_Show(LinkList *h_node);
//两表合并
void lianjie(LinkList *linka,LinkList *linkb);
//约瑟夫环
void yuesefu(LinkList *head,int,int,int);
#endif
/*===============================================
*   文件名称:list.c
*   创 建 者:xm     
*   创建日期:2022年07月29日
*   描    述:约瑟夫环
================================================*/
#include "list.h"
//创建头节点
LinkList *Creat_Linklist()
{
    LinkList *head=(LinkList*)malloc(sizeof(LinkList));
    if(NULL==head)
    {
        printf("malloc error!\n");
        return NULL;
    }
    head->data=-1;
    head->next=head;
    return head;
}
//判空
int Linklist_Is_Empty(LinkList *h_node)
{
    if(h_node->next==h_node)return 0;//表空返回0
    else return 1;
}
//求表长,为有效数据节点个数(即除去头节点)
int Linklist_length(LinkList *h_node)
{
    int len=0;
    LinkList *p=h_node->next;//p指向头节点后的第一个节点
    while(p!=h_node)
    {
        len++;
        p=p->next;

    }
    return len;
}
//打印
void Linklist_Show(LinkList *h_node)
{
    if(Linklist_Is_Empty(h_node)==0)
    {
        printf("表为空,无法打印\n");
        return ;
    }
    LinkList *p=h_node->next;//p指向头节点后的第一个节点
    while(p!=h_node)
    {
        printf("%d,",p->data);//打印数据
        p=p->next;

    }
    puts("");
}
//头插法
void Linklist_Insert_head(LinkList *h_node,data_t data)
{
    LinkList *p=(LinkList *)malloc(sizeof(LinkList));
    if(NULL==p)
    {
        printf("malloc new node error!\n");
        return ;
    }
    p->data=data;//存数据

    p->next=h_node->next;//新节点拿到下一节点的地址
    h_node->next=p; //上一节点刷新得到新节点的地址
}
//两链表的合并
void lianjie(LinkList *linka,LinkList *linkb)
{
    LinkList *p,*q;
    p=linka->next;
    q=linkb->next;
    while(p->next!=linka)
    {
        p=p->next;
    }
    while(q->next!=linkb)
    {
        q=q->next;
    }
    p->next=linkb->next;
    q->next=linka;

    linkb->next=linkb;
}
//约瑟夫环
void yuesefu(LinkList *head,int n,int k,int m)
{
    LinkList *q=NULL;
    Linklist_Insert_head(head,n);//先头插一个结点,即尾结点
    q=head->next;//保存尾结点地址,用于后面头尾连接
    while(--n)
    {
        Linklist_Insert_head(head,n);
    }
    Linklist_Show(head);//打印编号
    q->next=head->next;//最后一个节点连上第一个节点
    q=head->next;//重置q,用于后面指向起始结点
    free(head);//释放头结点
    while(--k)
    {
        q=q->next;
    }
    printf("起始结点编号=%d\n",q->data);
    LinkList *temp=NULL;//用于删除目标结点
    int count;//用于每轮计数
    while(q->next!=q)
    {
                
        count=m-1;
        while(--count)
        {
            q=q->next;
        }
        temp=q->next;//指向目标结点
        printf("%d,",temp->data);//打印淘汰者编号
        q->next=temp->next;//删除目标节点
        free(temp);//释放目标节点

        q=q->next;//指向新起始节点
    }
    printf("\n最后存活者编号%d\n",q->data);
}




/*===============================================
*   文件名称:main.c
*   创 建 者:     
*   创建日期:2022年07月29日
*   描    述:
================================================*/
#include "list.h"
int main(int argc, char *argv[])
{     
    //约瑟夫环 
    int n,k,m;
    printf("请输入人数 起始序号 次数\n");
    scanf("%d%d%d",&n,&k,&m);
    printf("n=%d,k=%d,m=%d\n",n,k,m);

    LinkList *head=Creat_Linklist();
    yuesefu(head,n,k,m);
    return 0;
} 

  • 11
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是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("出列顺序:"); while (n > 0) { // 找到要删除的节点 for (int i = 1; i < m; i++) { current = current->next; } // 输出出列的节点 printf("%d ", current->data); // 删除节点 head = deleteNode(head, current->data); current = current->next; n--; } printf("\n"); } int main() { int n, m; printf("请输入总人数n:"); scanf("%d", &n); printf("请输入报数m:"); scanf("%d", &m); josephusCircle(n, m); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值